[
  {
    "path": ".gitchangelog.rc",
    "content": "#output_engine = mustache(\"markdown\")\noutput_engine = mustache(\".release_notes.tpl\")\n\n\ntag_filter_regexp = r'^v?[0-9]+\\.[0-9]+(\\.[0-9]+)?$'\n\nignore_regexps = [\n    r'@minor', r'!minor',\n    r'@cosmetic', r'!cosmetic',\n    r'@refactor', r'!refactor',\n    r'@wip', r'!wip',\n    r'^([cC]hg|[fF]ix|[nN]ew)\\s*:\\s*[p|P]kg:',\n    r'^([cC]hg|[fF]ix|[nN]ew)\\s*:\\s*[d|D]ev:',\n    r'^(.{3,3}\\s*:)?\\s*[fF]irst commit.?\\s*$',\n    r'^$',  ## ignore commits with empty messages\n    r'release: *',\n]"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yaml",
    "content": "---\nname: Bug Report\ndescription: Report a bug encountered while using Hiddify\nlabels: [\"bug\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        ## Only English\n        For access to our user forums, please join [our Telegram group](https://t.me/hiddify_board).\n\n        Please make sure to provide a descriptive, deterministic, and reproducible report. It saves time for both the developers and users who are looking for solutions. Providing as much information as possible, including screenshots and logs, is highly appreciated. This will help us to better understand the issue and respond more effectively.\n\n        Please DO NOT use this template to ask questions. You can join [our Telegram group](https://t.me/hiddify_board) or [our Website](https://hiddify.com/app) to ask questions. This template is strictly for reporting bugs.\n  - type: checkboxes\n    id: confirm-search\n    attributes:\n      label: Search first\n      description: Please search [existing issues](https://github.com/hiddify/hiddify-app/issues) before reporting.\n      options:\n        - label: I searched and no similar issues were found\n          required: true\n  - type: dropdown\n    id: platform\n    attributes:\n      label: Platform/OS\n      description: What platform are you seeing the problem on?\n      multiple: true\n      options:\n        - Android\n        - Windows\n        - macOS\n        - Linux\n        - Android TV\n        - iOS\n        - HiddifyCli (Core)\n    validations:\n      required: true\n  - type: input\n    id: os\n    attributes:\n      label: \"OS version\"\n      description: \"Please provide the operating system version. (Example: Windows 10)\"\n    validations:\n      required: true\n  - type: input\n    id: version\n    attributes:\n      label: Hiddify Version\n      description: \"What version of Hiddify are you using?\"\n    validations:\n      required: true\n  - type: textarea\n    id: problem\n    attributes:\n      label: What Happened?\n      description: |\n        Please provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner.\n    validations:\n      required: true\n  - type: textarea\n    id: reproduce\n    attributes:\n      label: Minimal Reproducible Example (MRE)\n      description: |\n        Please tell us the steps to reproduce the bug. A [Minimal Reproducible Example (MRE)](https://stackoverflow.com/help/minimal-reproducible-example) is needed.\n      placeholder: |\n        1. Go to '...'\n        2. Click on '....'\n        3. Scroll down to '....'\n        4. See error\n    validations:\n      required: true\n  - type: textarea\n    id: expected\n    attributes:\n      label: Expected Behavior\n      description: |\n        Please tell us what's the behavior you expect.\n    validations:\n      required: false\n  - type: textarea\n    id: additional\n    attributes:\n      label: Additional Context\n      description: |\n        If applicable, add screenshots, screen recordings or additional context to help explain your problem.\n    validations:\n      required: false\n  - type: textarea\n    id: configs\n    attributes:\n      label: Application Config Options\n      description: Please copy and paste Application config.\n    validations:\n      required: false\n  - type: textarea\n    id: logs\n    attributes:\n      label: Relevant log output\n      description: Please copy and paste any relevant log output. This will be automatically formatted into code.\n    validations:\n      required: false\n  - type: checkboxes\n    id: ask-pr\n    attributes:\n      label: Are you willing to submit a PR? If you know how to fix the bug.\n      description: |\n        If you are not familiar with programming, you can skip this step.\n        If you are a developer and know how to fix the bug, you can submit a PR to fix it.\n        Your contributions are greatly appreciated and play a vital role in helping to improve the project!\n      options:\n        - label: I'm willing to submit a PR (Thank you!)\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Questions & Help\n    url: https://t.me/hiddify_board\n    about: Ask a question about Hiddify\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yaml",
    "content": "name: Feature Request\ndescription: Request a new feature\ntitle: '[FR] '\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        # Only English\n  - type: textarea\n    attributes:\n      label: Feature description\n      description: Please provide a clear and concise description of what you want to happen and what problem will this solve.\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/auto_translator.py",
    "content": "import i18n\nimport json\nfrom deep_translator import GoogleTranslator\nimport sys\nimport os\n\n\ndef get_path(lang):\n    base_dir = os.path.abspath('../assets/translations')\n    lang_file = f'strings_{lang}.i18n.json'\n    path = os.path.join(base_dir, lang_file)\n    if path.startswith(base_dir):\n        return path\n    else:\n        raise ValueError('Invalid language file path')\n\n\ndef read_translate(lang):\n    pat = get_path(lang)\n    if not os.path.isfile(pat):\n        return {}\n    with open(pat) as f:\n        return json.load(f)\n\n\ndef recursive_translate(src, dst, translator):\n    for sk, sv in src.items():\n        if type(sv) == str:\n            if sk not in dst or not dst[sk]:\n                dst[sk] = translator.translate(sv)\n                print(sk, sv, dst[sk])\n            if not dst[sk]:\n                del dst[sk]\n        else:\n            if sk not in dst:\n                dst[sk] = {}\n            recursive_translate(sv, dst[sk], translator)\n\n\nif __name__ == \"__main__\":\n    src = sys.argv[1]\n    dst = sys.argv[2]\n\n    src_pofile = read_translate(src)\n    dst_pofile = read_translate(dst)\n\n    translator = GoogleTranslator(source=src, target=dst if dst != 'zh' else \"zh-CN\")\n    recursive_translate(src_pofile, dst_pofile, translator)\n\n    with open(os.path.abspath(get_path(dst)), 'w') as df:\n        json.dump(dst_pofile, df, ensure_ascii=False, indent=4)\n"
  },
  {
    "path": ".github/change_version.sh",
    "content": "#! /bin/bash\nSED() { [[ \"$OSTYPE\" == \"darwin\"* ]] && sed -i '' \"$@\" || sed -i \"$@\"; }\necho \"previous version was $(git describe --tags $(git rev-list --tags --max-count=1))\"\necho \"WARNING: This operation will creates version tag and push to github\"\nif [ \"$(curl -o /dev/null -I -s -w \"%{http_code}\" https://github.com/hiddify/hiddify-core/releases/download/v${CORE_VERSION}/hiddify-core-linux-amd64.tar.gz)\" = \"404\" ]; then \n    echo \"Core v${CORE_VERSION} not Found\"; \n    exit 3; \nfi\n\n\ncversion_string=$(grep -e \"^version:\" pubspec.yaml | cut -d: -f2-)\ncstr_version=`echo \"${cversion_string}\" | sed -E -n 's/ *([0-9]+\\.[0-9]+\\.[0-9]+).*/\\1/p'`\n[ \"$cversion_string\" == \"\" ] && { echo \"getting old version error\"; exit 1 ; }\ncbuild_number=`echo \"${cversion_string}\" | sed -E -n 's/.*\\+([0-9]+)$/\\1/p'`\necho \"Current Version Name:${cstr_version}   Build Number:${cbuild_number}\"\nread -p \"new Version? (provide the next x.y.z semver) : \" TAG \necho $TAG \n[[ \"$TAG\" =~ ^[0-9]{1,2}\\.[0-9]{1,2}\\.[0-9]{1,2}(\\.dev)?$ ]] || { echo \"Incorrect tag. e.g., 1.2.3 or 1.2.3.dev\"; exit 1; } \nIFS=\".\" read -r -a VERSION_ARRAY <<< \"$TAG\" \nVERSION_STR=\"${VERSION_ARRAY[0]}.${VERSION_ARRAY[1]}.${VERSION_ARRAY[2]}\" \nBUILD_NUMBER=$(( ${VERSION_ARRAY[0]} * 10000 + ${VERSION_ARRAY[1]} * 100 + ${VERSION_ARRAY[2]} )) \necho \"version: ${VERSION_STR}+${BUILD_NUMBER}\" \necho \"====$cbuild_number\"\nSED \"s/^version: .*/version: ${VERSION_STR}\\+${BUILD_NUMBER}/g\" pubspec.yaml \nSED \"s/^msix_version: .*/msix_version: ${VERSION_ARRAY[0]}.${VERSION_ARRAY[1]}.${VERSION_ARRAY[2]}.0/g\" windows/packaging/msix/make_config.yaml \nSED \"s|CURRENT_PROJECT_VERSION = ${cbuild_number}|CURRENT_PROJECT_VERSION = ${BUILD_NUMBER}|g\" ios/Runner.xcodeproj/project.pbxproj \nSED \"s/MARKETING_VERSION = ${cstr_version}/MARKETING_VERSION = ${VERSION_STR}/g\" ios/Runner.xcodeproj/project.pbxproj \n\ngit tag ${TAG} > /dev/null \n\ngitchangelog > HISTORY.md || { git tag -d ${TAG}; echo \"Please run pip install gitchangelog pystache mustache markdown\"; exit 2; } \ngit tag -d ${TAG} > /dev/null \ngit add hiddify-core dependencies.properties ios/Runner.xcodeproj/project.pbxproj pubspec.yaml windows/packaging/msix/make_config.yaml HISTORY.md \ngit commit -m \"release: version ${TAG}\" \necho \"creating git tag : v${TAG}\" \ngit push \ngit tag v${TAG} \ngit push -u origin HEAD --tags \necho \"Github Actions will detect the new tag and release the new version.\"\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where the package manifests are located.\n# Please see the documentation for all configuration options:\n# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\n\nversion: 2\nupdates:\n  - package-ecosystem: \"gitsubmodule\" # See documentation for possible values\n    directory: \"/\" # Location of package manifests\n    schedule:\n      interval: \"daily\"\n    open-pull-requests-limit: 5\n\n\n"
  },
  {
    "path": ".github/release_message.md",
    "content": "<div align=center>\n    \n[![Release Downloads](https://img.shields.io/github/downloads/hiddify/hiddify-next/RELEASE_TAG/total?style=flat-square&logo=github)](https://img.shields.io/github/downloads/hiddify/hiddify-next/RELEASE_TAG/)\n\n</div>\n\n**Download based on your OS:**\n\n<div dir=\"rtl\">\n\n**بر اساس سیستم عامل خود دانلود کنید:**\n\n</div>\n\n\n\n<div align=left>\n<table>\n    <thead align=left>\n        <tr>\n            <th>OS</th>\n            <th>Download</th>\n        </tr>\n    </thead>\n    <tbody align=left>\n        <tr>\n        <td>Android</td><td>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-Android-universal.apk\"><img src=\"https://img.shields.io/badge/APK-Universal-044d29.svg?logo=android\"></a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-Android-arm64.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv8-168039.svg?logo=android\"></a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-Android-arm7.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv7-45bf55.svg?logo=android\"></a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-Android-x86_64.apk\"><img src=\"https://img.shields.io/badge/APK-x64-96ed89.svg?logo=android\"></a>\n        </td>\n        </tr>\n        <tr>\n            <td>Windows</td><td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-Windows-Setup-x64.Msix\"><img src=\"https://img.shields.io/badge/OfficialSetup-x64-0078d7.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-Windows-Setup-x64.exe\"><img src=\"https://img.shields.io/badge/Setup-x64-2d7d9a.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-Windows-Portable-x64.zip\"><img src=\"https://img.shields.io/badge/Portable-x64-67b7d1.svg?logo=windows\"></a>\n        </td>\n        </tr>\n        <tr>\n            <td>macOS (v10.15+)</td>\n            <td><a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-MacOS.dmg\"><img src=\"https://img.shields.io/badge/DMG-Universal-ea005e.svg?logo=apple\"></a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-MacOS-Installer.pkg\"><img src=\"https://img.shields.io/badge/PKG-Universal-bc544b.svg?logo=apple\" /></a></a></td>\n        </tr>\n        <tr>\n            <td>Linux</td>\n            <td><a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-Linux-x64.AppImage\"><img src=\"https://img.shields.io/badge/AppImage-x64-f84e29.svg?logo=linux\"> </a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-Debian-x64.deb\"><img src=\"https://img.shields.io/badge/DebPackage-x64-FF9966.svg?logo=debian\"> </a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/download/RELEASE_TAG/Hiddify-rpm-x64.rpm\"><img src=\"https://img.shields.io/badge/RpmPackage-x64-F1B42F.svg?logo=redhat\"> </a></td>\n        </tr>\n    </tbody>\n</table>\n\n\n</div>\n\n<div dir=\"ltr\">\n  \n**List of all changes:** [ChangeLog](https://github.com/hiddify/hiddify-app/blob/main/HISTORY.md)\n\n</div>\n"
  },
  {
    "path": ".github/sync_translate.sh",
    "content": "# key=\"FRu3eopQWgsvWmnycBXxv2eWpbUwGOu2\"\n# wget -O ../assets/translations/strings_en.i18n.json  \"https://localise.biz/api/export/locale/en-US.json?index=id&format=i18next4&key=$key\"\n# wget -O ../assets/translations/strings_fa.i18n.json  \"https://localise.biz/api/export/locale/fa.json?index=id&format=i18next4&key=$key\"\n# wget -O ../assets/translations/strings_zh.i18n.json  \"https://localise.biz/api/export/locale/zh.json?index=id&format=i18next4&key=$key\"\n# # # wget -O ../assets/translations/strings_pt.i18n.json  \"https://localise.biz/api/export/locale/pt.json?index=id&format=i18next4&key=$key\"\n# wget -O ../assets/translations/strings_ru.i18n.json  \"https://localise.biz/api/export/locale/ru.json?index=id&format=i18next4&key=$key\"\n\n\n\npip install polib deep-translator python-i18n\n\n# python3 auto_translator.py fa en\npython3 auto_translator.py en fa\npython3 auto_translator.py en zh-CN\n# python3 auto_translator.py en pt\npython3 auto_translator.py en ru\npython3 auto_translator.py en tr\npython3 auto_translator.py en es\n\n\n\nfunction update_localise(){\n    lang=$1\n\tpat=\"../assets/translations/strings_${lang}.i18n.json\"\n\t# if [[ $lang == 'en' ]];then\n\t# \tpat=\"../assets/translations/strings.i18n.json\"\n\t# fi\n# curl -X POST \"https://localise.biz/api/import/json?locale=$lang&key=$LOCALIZ_KEY\" \\\ncurl \"https://localise.biz/api/import/json?format=i18next4&delete-absent=false&ignore-existing=false&locale=$lang&flag-new=Provisional&key=$LOCALIZ_KEY\" \\\n  -H 'Accept: application/json' \\\n  --data-binary @$pat \n  }\n\n\n# update_localise en\n# update_localise fa\n# update_localise zh\n# # # # update_localise pt\n# update_localise ru"
  },
  {
    "path": ".github/workflows/add_signed_microsft.yml",
    "content": "name: Upload store MSIX to release\n\npermissions:\n  contents: write\n\non:\n  release:\n    types: [released]   # Run the action when a GitHub release is published\n\n  # schedule:\n  #   - cron:  '0 */6 * * *'  # Run the action every 6 hours\n\n  workflow_dispatch:    # Manually run the action\n\njobs:\n  upload-store-msix-to-release:\n    runs-on: ubuntu-latest\n\n    steps:\n    - name: Upload store MSIX to release\n      uses: hiddify/Upload-Microsoft-Store-MSIX-Package-to-GitHub-Release@develop\n      with:\n        store-id: 9pdfnl3qv2s5\n        token: ${{ secrets.GITHUB_TOKEN }}\n        asset-name-pattern: Hiddify-Windows-Setup-x64\t\t# Optional"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build\non:\n  workflow_call:\n    inputs:\n      upload-artifact:\n        type: boolean\n        default: true\n      tag-name:\n        type: string\n        default: \"draft\"\n      channel:\n        type: string\n        default: \"dev\"\n\nenv:\n  IS_GITHUB_ACTIONS: 1\n  CHANNEL: \"${{ inputs.channel }}\"\n  FLUTTER_VERSION: '3.38.5'\n  NDK_VERSION: r28c\n  UPLOAD_ARTIFACT: \"${{ inputs.upload-artifact }}\"\n  TAG_NAME: \"${{ inputs.tag-name }}\"\n  TARGET_NAME_gz: \"Hiddify-Linux-x64-AppImage.tar\"\n  TARGET_NAME_AppImage: \"Hiddify-Linux-x64-AppImage\"\n  TARGET_NAME_deb: \"Hiddify-Debian-x64\"\n  # TARGET_NAME_rpm: \"Hiddify-rpm-x64\"\n  TARGET_NAME_apk: \"Hiddify-Android\"\n  TARGET_NAME_aab: \"Hiddify-Android\"\n  TARGET_NAME_exe: \"Hiddify-Windows-Setup-x64\"\n  TARGET_NAME_msix: \"Hiddify-Windows-x64\"\n  TARGET_NAME_zip: \"Hiddify-Windows-Portable-x64\"\n  TARGET_NAME_dmg: \"Hiddify-MacOS\"\n  TARGET_NAME_pkg: \"Hiddify-MacOS-Installer\"\n  TARGET_NAME_ipa: \"Hiddify-iOS\"\n  \n\njobs:\n  test:\n    outputs:\n      draftBuildCode: ${{ steps.draftBuildCode.outputs.datetime }}\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: subosito/flutter-action@v2.21.0 #issue with 2.13\n        with:\n          flutter-version: ${{ env.FLUTTER_VERSION }}\n          channel: 'stable'\n          cache: true\n          \n      - name: Prepare\n        run: make linux-amd64-prepare\n      - name: Test\n        run: flutter test\n\n      - name: make draftBuildCode\n        id: draftBuildCode\n        run: echo \"::set-output name=datetime::$(date +'%d.%H.%M')\"\n\n\n  build:\n    needs: test\n    permissions: write-all\n    continue-on-error: true\n\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - platform: android-apk\n            os: ubuntu-latest\n            targets: apk\n\n          - platform: android-aab\n            os: ubuntu-latest\n            targets: aab\n\n          - platform: windows\n            os: windows-latest\n            aarch: amd64\n            targets: exe,msix,zip\n\n          - platform: linux\n            os: ubuntu-22.04\n            aarch: amd64\n            targets: deb,gz,AppImage\n\n          # - platform: linux-amd64\n          #   os: ubuntu-22.04\n          #   aarch: amd64\n          #   targets: deb,gz\n\n          # - platform: linux-arm64\n          #   os: ubuntu-24.04-arm\n          #   aarch: arm64\n          #   targets: deb,gz\n\n          # - platform: linux-amd64-musl\n          #   os: ubuntu-22.04\n          #   aarch: amd64\n          #   targets: deb,gz\n\n          # - platform: linux-arm64-musl\n          #   os: ubuntu-24.04-arm\n          #   aarch: arm64\n          #   targets: deb,gz\n            \n          - platform: macos\n            os: macos-15\n            aarch: universal\n            targets: dmg,pkg\n            \n          # - platform: ios\n          #   os: macos-15\n          #   aarch: universal\n          #   filename: hiddify-ios\n          #   targets: ipa\n    runs-on: ${{ matrix.os }}\n    steps:\n      - name: checkout\n        uses: actions/checkout@v6\n\n      - name: Import Apple Codesign Certificates\n        if: ${{ inputs.upload-artifact && startsWith(matrix.os,'macos') }}\n        uses: apple-actions/import-codesign-certs@v6\n        with: \n            p12-file-base64: \"${{ secrets.APPLE_CERTIFICATE_P12 }}\"\n            p12-password: \"${{ secrets.APPLE_CERTIFICATE_P12_PASSWORD }}\"\n\n      - name: Import Apple Mobile Provisioning Profile\n        if: ${{ inputs.upload-artifact && startsWith(matrix.os,'macos') }}\n        run: |\n           mkdir -p ~/Library/MobileDevice/Provisioning\\ Profiles\n           echo \"${{secrets.APPLE_MOBILE_PROVISIONING_PROFILES_TARGZ_BASE64}}\"|base64 --decode | tar xz -C ~/Library/MobileDevice/Provisioning\\ Profiles\n           ls ~/Library/MobileDevice/Provisioning\\ Profiles\n           security unlock-keychain -p \"\" signing_temp.keychain\n           security find-identity -v -p codesigning\n        #   ls ~/Library/MobileDevice/Provisioning\\ Profiles\n        #   echo \"${{secrets.NEW_APPLE_MOBILE_PROVISIONING_PROFILES_TARXZ_BASE64}}\"|base64 --decode | tar xJ -C ~/Library/MobileDevice/Provisioning\\ Profiles\n        #   # echo \"${{secrets.NEW_APPLE_MOBILE_PROVISIONING_PROFILES_TARGZ_BASE64_2}}\"|base64 --decode | tar xz -C ~/Library/MobileDevice/Provisioning\\ Profiles\n          \n\n\n      # - name: Setup Flutter for arm64\n      #   if: ${{ startsWith(matrix.platform,'linux-arm64') }}\n      #   uses: hurelhuyag/flutter-arm64-action@HEAD\n      #   with:\n      #     channel: 'stable'\n      #     flutter-version: ${{ env.FLUTTER_VERSION }}\n\n      - name: Setup Flutter\n        uses: subosito/flutter-action@v2.21.0 #issue with 2.13\n        with:\n          flutter-version: ${{ env.FLUTTER_VERSION }}\n          # flutter-version-file: pubspec.yaml\n          channel: 'stable'\n          cache: true\n\n      - name: Clean up disk space\n        if: startsWith(matrix.platform,'android')\n        run: |\n          df -h\n          sudo rm -rf /usr/share/dotnet\n          df -h\n          sudo rm -rf /opt/ghc\n          df -h\n          sudo rm -rf /opt/hostedtoolcache/CodeQL\n          df -h\n          rm -rf ~/.gradle/caches\n          df -h\n          sudo apt-get autoremove -y\n          df -h\n          sudo apt-get clean \n          df -h\n          tree\n      \n      - name: Setup Java\n        if: startsWith(matrix.platform,'android')\n        uses: actions/setup-java@v5\n        with:\n          distribution: 'zulu'\n          java-version: 17\n      # - name: Setup NDK\n      #   if: startsWith(matrix.platform,'android')\n      #   uses: nttld/setup-ndk@v1\n      #   id: setup-ndk\n      #   with:\n      #     ndk-version: ${{ env.NDK_VERSION }}\n      #     add-to-path: true\n      #     link-to-sdk: true\n\n      - name: Setup Android SDK\n        uses: android-actions/setup-android@v3\n        if: startsWith(matrix.platform,'android')\n      # - name: Cache Android SDK\n      #   uses: actions/cache@v5\n      #   if: startsWith(matrix.platform,'android')\n      #   with:\n      #     path: |\n      #       /usr/local/lib/android/sdk\n      #     key: android-sdk-${{ runner.os }}-${{ env.NDK_VERSION }}\n      #     restore-keys: |\n      #       android-sdk-${{ runner.os }}-      \n      - name: Cache Gradle\n        uses: actions/cache@v5\n        if: startsWith(matrix.platform,'android')\n\n        with:\n          path: |\n            ~/.gradle/caches\n            ~/.gradle/wrapper\n          key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}\n          restore-keys: |\n            gradle-${{ runner.os }}-\n                  \n      - name: Setup dependencies\n        run: |\n          make ${{ matrix.platform }}-install-deps  \n          echo \"$HOME/.pub-cache/bin\" >> $GITHUB_PATH\n\n      - name: Setup Android Signing Properties\n        if: ${{ inputs.upload-artifact && startsWith(matrix.platform,'android') }}\n        run: |\n          echo \"${{ secrets.ANDROID_SIGNING_KEY }}\" | base64 --decode > android/key.jks\n          echo \"storeFile=$(pwd)/android/key.jks\" > android/key.properties\n          echo \"storePassword=${{ secrets.ANDROID_SIGNING_STORE_PASSWORD }}\" >> android/key.properties\n          echo \"keyPassword=${{ secrets.ANDROID_SIGNING_KEY_PASSWORD }}\" >> android/key.properties\n          echo \"keyAlias=${{ secrets.ANDROID_SIGNING_KEY_ALIAS }}\" >> android/key.properties\n\n      - name: Setup Windows Signing Properties\n        if: ${{ inputs.upload-artifact && startsWith(matrix.platform,'windows') }}\n        run: |\n            [IO.File]::WriteAllBytes(\"windows\\sign.pfx\", [Convert]::FromBase64String(\"${{ secrets.WINDOWS_SIGNING_KEY }}\"))\n            (Get-Content \"windows\\packaging\\msix\\make_config.yaml\") -replace '^certificate_password:.*$', 'certificate_password: ${{ secrets.WINDOWS_SIGNING_PASSWORD }}' | Set-Content \"windows\\packaging\\msix\\make_config.yaml\"\n        \n      # - name: Temporary disable Permission Handler for windows due to its issue in permission\n      #   if: ${{ startsWith(matrix.platform,'windows') }}\n      #   run: |\n      #     (Get-Content -Path \"pubspec.yaml\") -notmatch \"permission_handler\" | Set-Content -Path \"pubspec.yaml\"\n      #     (Get-Content -Path \"lib\\features\\profile\\add\\add_profile_modal.dart\") -notmatch \"qr_code_scanner_screen\" | Set-Content -Path \"lib\\features\\profile\\add\\add_profile_modal.dart\"\n      #     (Get-Content -Path lib\\features\\profile\\add\\add_profile_modal.dart) -replace 'await QRCodeScannerScreen\\(\\).open\\(context\\);', 'null;' | Set-Content -Path lib\\features\\profile\\add\\add_profile_modal.dart\n      #     Remove-Item -Path \"lib\\features\\common\\qr_code_scanner_screen.dart\"\n\n\n\n\n      - name: Prepare for ${{ matrix.platform }}\n        run: |\n          make ${{ matrix.platform }}-prepare\n\n\n      - name: Build ${{ matrix.platform }}\n        env:\n          SENTRY_DSN: ${{ secrets.SENTRY_DSN }}\n        run: |\n          make ${{ matrix.platform }}-release\n\n      - name: Code Sign\n        if: ${{ inputs.upload-artifact && startsWith(matrix.platform,'windows') }}\n        uses: hiddify/signtool-code-sign-sha256@main\n        with:\n          certificate: '${{ secrets.WINDOWS_SIGNING_KEY }}'\n          cert-password: '${{ secrets.WINDOWS_SIGNING_PASSWORD }}'\n          cert-sha1: '${{ secrets.WINDOWS_SIGNING_SHA1 }}'\n          folder: 'dist'\n          timestamp-server: 'http://timestamp.digicert.com'\n          recursive: true\n          description: 'Hiddify'\n\n      - name: Copy to out Windows\n        if: matrix.platform == 'windows'\n        shell: pwsh\n        run: |\n          Get-ChildItem -Path dist -Recurse | Select-Object FullName\n          New-Item -ItemType Directory -Path \"out\" -Force | Out-Null\n          $targets = \"${{ matrix.targets }}\".Split(',')\n          foreach ($ext in $targets) {\n            $ext = $ext.Trim()\n            $key = \"TARGET_NAME_$ext\"\n            $targetName = (Get-Item \"env:$key\").Value\n            \n            $files = Get-ChildItem -Path dist -Recurse -Filter \"*.$ext\"\n            \n            foreach ($file in $files) {\n                $destination = Join-Path -Path \"out\" -ChildPath \"$targetName.$ext\"\n                Move-Item -Path $file.FullName -Destination $destination -Force\n            }\n          }\n          Get-ChildItem -Path out\n          \n      - name: Upload Debug Symbols\n        if: ${{ inputs.upload-artifact && inputs.tag-name != 'draft' }}\n        env:\n          SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}\n          SENTRY_ORG: ${{ secrets.SENTRY_ORG }}\n          SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}\n          SENTRY_DIST: ${{ matrix.platform == 'android-aab' && 'google-play' || 'general' }}\n        run: |\n          dart pub global activate sentry_dart_plugin\n          dart run sentry_dart_plugin \n      \n      \n\n              \n      - name: Copy to out Android APK\n        if: matrix.platform == 'android-apk'\n        run: |\n          mkdir out\n          ls -R ./build/app/outputs\n          cp ./build/app/outputs/flutter-apk/*arm64-v8a*.apk out/${TARGET_NAME_apk}-arm64.apk || echo \"no arm64 apk\"\n          cp ./build/app/outputs/flutter-apk/*armeabi-v7a*.apk out/${TARGET_NAME_apk}-arm7.apk || echo \"no arm7 apk\"\n          cp ./build/app/outputs/flutter-apk/*x86_64*.apk out/${TARGET_NAME_apk}-x86_64.apk || echo \"no x64 apk\"\n          cp ./build/app/outputs/flutter-apk/app-release.apk out/${TARGET_NAME_apk}-universal.apk || echo \"no universal apk\"\n\n      - name: Copy to out Android AAB\n        if: matrix.platform == 'android-aab'\n        run: |\n          mkdir out\n          ls -R ./build/app/outputs\n          cp ./build/app/outputs/bundle/release/app-release.aab out/hiddify-android-market.aab || echo \"no aab\"\n\n      - name: Copy to out unix\n        if: startsWith(matrix.platform,'linux') || matrix.platform == 'macos' || matrix.platform == 'ios'\n        run: |\n          ls -R dist/\n          mkdir out\n          mkdir tmp_out\n          \n          for EXT in $(echo ${{ matrix.targets }} | tr ',' '\\n'); do\n            KEY=TARGET_NAME_${EXT}\n            FILENAME=${!KEY}\n            echo \"For $EXT ($KEY) filename is ${FILENAME}\"\n            mv dist/*/*.$EXT tmp_out/${FILENAME}.$EXT\n            ls tmp_out\n            [[ \"$EXT\" != \"gz\" ]] && chmod +x tmp_out/${FILENAME}.$EXT || echo \"Skipping chmod for gz\"\n            if [ \"${{matrix.platform}}\" == \"linux\" ];then\n              cp ./.github/help/linux/* tmp_out/\n            else\n              cp ./.github/help/mac-windows/* tmp_out/\n            fi\n            if [[ \"${{matrix.platform}}\" == 'ios' ]];then\n              echo mv tmp_out/${FILENAME}.$EXT out/\n              mv tmp_out/${FILENAME}.$EXT out/\n            else\n              cd tmp_out\n              # 7z a ${FILENAME}.zip ./\n              # mv ${FILENAME}.zip ../out/\n              # [[ $EXT == 'AppImage' ]]&& mv ${FILENAME}.$EXT ../out/ # added for appimage link\n              mv ${FILENAME}.$EXT ../out/\n              cd ..\n            fi\n          done\n\n      - name: Upload Artifact\n        if: env.UPLOAD_ARTIFACT == 'true'\n        uses: actions/upload-artifact@v6\n        with:\n          name: ${{matrix.platform}}\n          path: ./out\n          retention-days: 1\n\n      - name: Clean up keychain and provisioning profile\n        if: ${{ always() && startsWith(matrix.os,'macos')}}\n        run: |\n          security delete-keychain $RUNNER_TEMP/app-signing.keychain-db ||echo ok\n          rm ~/Library/MobileDevice/Provisioning\\ Profiles/*.mobileprovision ||echo ok\n  update-draft:\n    permissions: write-all\n    if: ${{ inputs.upload-artifact }}\n    needs: [build]\n    runs-on: ubuntu-latest\n    steps:\n      - name: checkout\n        uses: actions/checkout@v6\n        with:\n          # by default, it uses a depth of 1\n          # this fetches all history so that we can read each commit\n          fetch-depth: 0\n      - name: Download Artifact\n        uses: actions/download-artifact@v7\n        with:\n          merge-multiple: true\n          pattern: \"*\"\n          path: ./out/\n          \n\n      - name: Display Files Structure\n        run: ls -R\n        working-directory: ./out\n\n      - name: Delete Current Release Assets\n        uses: 8Mi-Tech/delete-release-assets-action@main\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          tag: 'draft'\n          deleteOnlyFromDrafts: false\n          \n      - name: prepare_release_message\n        continue-on-error: true\n        run: |\n          set +e \n          sed 's|RELEASE_TAG|${{ env.TAG_NAME }}|g' ./.github/release_message.md > release.md\n          pip install gitchangelog pystache mustache markdown\n          prelease=$(curl --silent \"https://api.github.com/repos/hiddify/hiddify-app/releases/latest\" | grep -Po '\"tag_name\": \"\\K([^\"]*)') \n          echo -e \"\\n\\n<details markdown=1><summary>All changes from $current to the latest commit:</summary>\\n\\n\">>release.md\n          gitchangelog \"${prelease}..\" >> release.md  2>&1 || echo \"Error in gitchangelog\"\n          echo -e \"\\n\\n</details>\">>release.md\n      - name: Create or Update Draft Release\n        uses: softprops/action-gh-release@v2\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        with:\n          files: ./out/*\n          name: 'draft'\n          tag_name: 'draft'\n          body_path: './release.md'\n          prerelease: true\n\n      - name: Create or Update Draft Release\n        uses: softprops/action-gh-release@v2\n        env:\n          GITHUB_TOKEN: ${{ secrets.TOKEN_FOR_HIDDIFY_APP_REPO }}\n          GITHUB_REPOSITORY: hiddify/hiddify-app\n        with:\n          files: ./out/*\n          name: 'draft'\n          tag_name: 'draft'\n          body_path: './release.md'\n          target_commitish: '530bf77839a74d4f13847ba244a20734ac7ab119'\n          prerelease: true\n          repository: hiddify/hiddify-app\n\n  upload-release:\n    permissions: write-all\n    if: ${{ inputs.upload-artifact && inputs.tag-name != 'draft' }}\n    needs: [build]\n    runs-on: ubuntu-latest\n    steps:\n      - name: checkout\n        uses: actions/checkout@v6\n\n      - name: Download Artifact\n        uses: actions/download-artifact@v7\n        with:\n          merge-multiple: true\n          pattern: \"*\"\n          path: ./out/\n\n      - name: Display Files Structure\n        run: |\n          ls -R ./out\n          ls -R ./.github/\n          ls -R ./.git/\n          mv out/hiddify-android-market.aab  hiddify-android-market.aab\n\n      - name: prepare_release_message\n        run: |\n          sed 's|RELEASE_TAG|${{ env.TAG_NAME }}|g' ./.github/release_message.md >> release.md\n\n      - name: Upload Release\n        uses: softprops/action-gh-release@v2\n        if: ${{ success() }}\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        with:\n          # prerelease: ${{ env.CHANNEL == 'dev' }}\n          prerelease: true\n          tag_name: ${{ env.TAG_NAME }}\n          body_path: './release.md'\n          files: ./out/*\n\n      - name: Create service_account.json\n        run: echo '${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}' > service_account.json\n\n      - name: Deploy to Google Play Internal Testers\n        uses: r0adkll/upload-google-play@v1\n        with:\n          serviceAccountJson: service_account.json\n          packageName: app.hiddify.com\n          releaseName: ${{ env.TAG_NAME }}\n          releaseFiles: ./hiddify-android-market.aab\n          track: 'beta'\n\n\n  upload-to-testflight:\n    needs: [build]\n    if: ${{ inputs.upload-artifact &&  inputs.tag-name != 'draft' }}\n    #if: ${{ inputs.upload-artifact }}\n    runs-on: macOS-latest\n    timeout-minutes: 30\n    steps:\n      - name: Download Artifact\n        uses: actions/download-artifact@v7\n        with:\n          merge-multiple: true\n          pattern: \"*ios*\"\n          path: ./out/\n\n      - uses: Apple-Actions/import-codesign-certs@v6\n        with:\n          p12-file-base64: ${{ secrets.APPLE_UPLOAD_CERTIFICATE_P12 }}\n          p12-password: ${{ secrets.APPLE_CERTIFICATE_P12_PASSWORD }}\n\n      - uses: Apple-Actions/download-provisioning-profiles@v1\n        with:\n          bundle-id: app.hiddify.com\n          issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}\n          api-key-id: ${{ secrets.APPSTORE_API_KEY_ID }}\n          api-private-key: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}\n      - uses: Apple-Actions/download-provisioning-profiles@v1\n        with:\n          bundle-id: app.hiddify.com.SingBoxPacketTunnel\n          issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}\n          api-key-id: ${{ secrets.APPSTORE_API_KEY_ID }}\n          api-private-key: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}\n  \n\n\n      - name: Import Apple Mobile Provisioning Profile\n        run: |\n          mkdir -p ~/Library/MobileDevice/Provisioning\\ Profiles\n          echo \"${{secrets.APPLE_DIST_PROVISIONING_PROFILES_TARGZ_BASE64}}\"|base64 --decode | tar xz -C ~/Library/MobileDevice/Provisioning\\ Profiles\n        #echo \"${{secrets.NEW_APPLE_STORE_PROVISIONING_PROFILES_TARXZ_BASE64}}\"|base64 --decode | tar xJ -C ~/Library/MobileDevice/Provisioning\\ Profiles\n\n      - uses: Apple-Actions/upload-testflight-build@v4\n        with:\n          app-path: 'out/Hiddify-iOS.ipa' \n          issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}\n          api-key-id: ${{ secrets.APPSTORE_API_KEY_ID }}\n          api-private-key: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\non:\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - 'docs/**'\n      - 'test.configs/**'\n      - '.vscode/'\n      - 'appcast.xml'\n  push:\n    branches:\n       - main\n       - dev\n       - android-fix-action-bug\n       - new-design-v2 \n    paths-ignore:\n      - '**.md'\n      - 'docs/**'\n      - '.vscode/'\n      - 'appcast.xml'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  run:\n    uses: ./.github/workflows/build.yml\n    secrets: inherit\n    permissions: write-all\n    if: \"${{!contains(github.event.head_commit.message, 'release: version')}}\"\n    with:\n      upload-artifact: ${{ github.event_name == 'push' }}\n      \n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\non:\n  push:\n    tags:\n      - 'v[0-9]+.[0-9]+.[0-9]+'\n      - 'v[0-9]+.[0-9]+.[0-9]+.*'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build-release:\n    uses: ./.github/workflows/build.yml\n    secrets: inherit\n    permissions: write-all\n    with:\n      upload-artifact: true\n      tag-name: \"${{ github.ref_name }}\"\n      channel: \"${{ github.ref_type == 'tag' && endsWith(github.ref_name, 'dev') && 'dev' || github.ref_type != 'tag' && 'dev' || 'prod' }}\"\n"
  },
  {
    "path": ".github/workflows/stale.yml",
    "content": "name: Mark stale issues and pull requests\n\non:\n  schedule:\n    - cron: \"30 8 * * *\"\n\njobs:\n  stale:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/stale@v10\n        with:\n          # stale-issue-message: 'With the release of v4.0.0 (pre-release), most reported issues have been fixed. We’re closing all current issues to start fresh.If you’re still experiencing the problem, please open a new issue and let us know.'\n          days-before-stale: 30\n          days-before-close: 10\n          operations-per-run: 60\n"
  },
  {
    "path": ".github/workflows/winget.yml",
    "content": "name: Publish to WinGet\non:\n  release:\n    types: [released]\n\nenv:\n    IDENTIFIER: ${{ endsWith(github.event.release.tag_name, 'dev') && 'Hiddify.Next.Beta' || 'Hiddify.Next' }}\n\njobs:\n  publish:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: vedantmgoyal9/winget-releaser@2\n        with:\n          identifier: ${{ env.IDENTIFIER }}\n          version: ${{ github.event.release.tag_name }}\n          token: ${{ secrets.WINGET_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "\n# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.sentry-native\n.DS_Store\n.atom/\n.build/\n.buildlog/\n.history\n.svn/\n.swiftpm/\nmigrate_working_dir/\n.github/help\n# IntelliJ related\n*.iml\n*.ipr\n*.iws\n.idea/\n\n# The .vscode folder contains launch configuration and tasks you configure in\n# VS Code which you may wish to be included in version control, so this line\n# is commented out by default.\n#.vscode/\n\n# Flutter/Dart/Pub related\n**/doc/api/\n**/ios/Flutter/.last_build_id\n.dart_tool/\n.flutter-plugins\n.flutter-plugins-dependencies\n.packages\n.pub-cache/\n.pub/\n/build/\n\n# generated files\n**/*.g.dart\n**/*.freezed.dart\n**/*.mapper.dart\n**/*.gen.dart\n**/*.dll\n**/*.dylib\n**/*.xcframework\n/dist/\n/dist_docker/\n\n/assets/core/*\n!/assets/core/.gitkeep\n\n# Symbolication related\napp.*.symbols\n\n# Obfuscation related\napp.*.map.json\n\n# Android Studio will place build artifacts here\n/android/app/debug\n/android/app/profile\n/android/app/release\n\n\n/data\n.cxx\n\n# Windows Self-Signed for msix\nwindows/sign.pfx\nwindows/sign.cer"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"hiddify-core\"]\n\tpath = hiddify-core\n\turl = ssh://git@github.com/hiddify/hiddify-core\n\tbranch = v3\n"
  },
  {
    "path": ".metadata",
    "content": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrades etc.\n#\n# This file should be version controlled and should not be manually edited.\n\nversion:\n  revision: \"ef1af02aead6fe2414f3aafa5a61087b610e1332\"\n  channel: \"stable\"\n\nproject_type: app\n\n# Tracks metadata for the flutter migrate command\nmigration:\n  platforms:\n    - platform: root\n      create_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n      base_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n    - platform: android\n      create_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n      base_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n    - platform: ios\n      create_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n      base_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n    - platform: linux\n      create_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n      base_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n    - platform: macos\n      create_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n      base_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n    - platform: windows\n      create_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n      base_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332\n\n  # User provided section\n\n  # List of Local paths (relative to this file) that should be\n  # ignored by the migrate tool.\n  #\n  # Files that are not part of the templates will be ignored by default.\n  unmanaged_files:\n    - 'lib/main.dart'\n    - 'ios/Runner.xcodeproj/project.pbxproj'\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n    \"overrides\": [\n        {\n            \"files\": \".github/**\",\n            \"options\": {\n                \"singleQuote\": true\n            }\n        }\n    ]\n}"
  },
  {
    "path": ".release_notes.tpl",
    "content": "{{#general_title}}\n# {{{title}}}\n\n\n{{/general_title}}\n{{#versions}}\n## {{{label}}}\n\n{{#sections}}\n#### {{{label}}}\n\n{{#commits}}\n* {{{subject}}} \n{{#body}}\n  _{{{body}}}_\n{{/body}}\n\n{{/commits}}\n{{/sections}}\n\n\n{{/versions}}"
  },
  {
    "path": ".stignore",
    "content": "#include /.stignore\n#include /android/.stignore\n#include /ios/.stignore\n#include /linux/.stignore\n#include /windows/.stignore\n#include /macos/.stignore\n\n.git\n\n.DS_Store\n.idea\n.dart_tool\n\n.flutter-plugins\n.flutter-plugins-dependencies\n\n.packages\n.pub-cache\n.pub\nbuild\n\n*.log\n*.iml\n*.ipr\n*.iws\n\n**/ios/Flutter/.last_build_id\n\n/android/app/debug\n/android/app/profile\n/android/app/release\n"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n\t\"recommendations\": [\n\t\t\"dart-code.dart-code\",\n\t\t\"dart-code.flutter\",\n\t\t\"github.vscode-github-actions\",\n\t\t\"golang.go\",\n\t\t\"redhat.vscode-yaml\",\n\t\t\"codeium.codeium\",\n\t\t\"kangping.protobuf\"\n\t]\n}"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"go Package\",\n            \"type\": \"go\",\n            \"request\": \"launch\",\n            \"mode\": \"auto\",\n            \"cwd\": \"./hiddify-core\",\n            \"program\": \"./hiddify-core/cmd/main\",\n            // \"args\": [\"build\",\"-c\",\"a.txt\",\"-d\",\"b.txt\",\"--full-config\"] ,\n            // \"args\": [\"temp\"] ,\n            // \"args\":[\"profile\",\"https://raw.githubusercontent.com/hiddify/hiddify-next/refs/heads/main/test.configs/warp\"],\n            \"args\": [\n                \"run\",\n                \"-c\",\n                \"https://raw.githubusercontent.com/hiddify/hiddify-next/refs/heads/main/test.configs/warp\"\n            ],\n            \"buildFlags\": \"-tags with_clash_api,with_gvisor,with_quic,with_wireguard,with_grpc,with_ech,with_utls,with_reality_server\"\n        },\n        {\n            \"name\": \"Hiddify Dev\",\n            \"request\": \"launch\",\n            \"type\": \"dart\",\n            \"flutterMode\": \"debug\",\n            \"program\": \"lib/main.dart\",\n            // \"args\": [\"-d\",\"192.168.1.35:36463\"]\n        },\n        {\n            \"name\": \"Hiddify Dev Windows Portable\",\n            \"request\": \"launch\",\n            \"type\": \"dart\",\n            \"flutterMode\": \"debug\",\n            \"program\": \"lib/main.dart\",\n            \"args\": [\n                \"-d\",\n                \"windows\",\n                \"--dart-define=portable=true\"\n            ]\n        },\n        {\n            \"name\": \"Hiddify Dev Release\",\n            \"request\": \"launch\",\n            \"type\": \"dart\",\n            \"flutterMode\": \"release\",\n            \"program\": \"lib/main.dart\",\n        },\n        {\n            \"name\": \"Hiddify Dev Profile\",\n            \"request\": \"launch\",\n            \"type\": \"dart\",\n            \"flutterMode\": \"profile\",\n            \"program\": \"lib/main.dart\",\n        },\n        {\n            \"name\": \"Hiddify Prod\",\n            \"request\": \"launch\",\n            \"type\": \"dart\",\n            \"flutterMode\": \"release\",\n            \"program\": \"lib/main_prod.dart\",\n        },\n        {\n            \"name\": \"Attach: Design for iPad\",\n            \"request\": \"attach\",\n            \"type\": \"dart\",\n            \"program\": \"lib/main.dart\",\n            \"args\": [\n                \"--app-id\",\n                \"app.hiddify.com\"\n            ],\n            \"deviceId\": \"mac-designed-for-ipad\",\n        }\n    ]\n}"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n\t\"[dart]\": {\n\t\t\"editor.defaultFormatter\": \"Dart-Code.dart-code\",\n        \"editor.formatOnSave\": true,\n        \"editor.formatOnType\": true,\n        \"editor.tabSize\": 2,\n        \"editor.detectIndentation\": false,\n        \"editor.selectionHighlight\": false,\n        \"editor.suggest.snippetsPreventQuickSuggestions\": false,\n        \"editor.suggestSelection\": \"first\",\n        \"editor.tabCompletion\": \"onlySnippets\",\n        \"editor.wordBasedSuggestions\": \"off\"\n\t},\n\n    \"html.format.wrapLineLength\": 250\n\t\n}"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n## [0.16.0.dev] - 2024-2-18\n\n### New Features and Improvements\n\n- Changed App name to **Hiddify**\n- Changed App icon\n- Added Mux (**Experimental**)\n- Added Cloudflare WARP (**Experimental**)\n- Added connection info\n  - when connected, name of the active node, speed and IP address are shown on home page\n  - delay indicator below connection button shows active node's ping\n- Added VPN Service (Windows & Linux) (**Experimental**)\n  - VPN Service circumvents need for administrator permission while using TUN\n- Changed in-app icons (using [Fluent UI System Icons](https://github.com/microsoft/fluentui-system-icons))\n- Redesigned navigation flow, separating config options\n- Added haptic feedback\n- Added detailed subscription info in profile edit page\n- Added Chinese Taiwan language. [PR#410](https://github.com/hiddify/hiddify-next/pull/410) by [junlin03](https://github.com/junlin03) and [PR#491](https://github.com/hiddify/hiddify-next/pull/491) by [kouhe3](https://github.com/kouhe3)\n- Added Japanese Readme. [PR#371](https://github.com/hiddify/hiddify-next/pull/371) by [Ikko Eltociear Ashimine](https://github.com/eltociear)\n\n### Bug Fixes\n\n- Fixed TLS Tricks bugs\n- Fixed logs on iOS. [PR#414](https://github.com/hiddify/hiddify-next/pull/414) by [Amir Mohammadi](https://github.com/amirsaam) and [PR#416](https://github.com/hiddify/hiddify-next/pull/416) by [Ebrahim Tahernejad](https://github.com/EbrahimTahernejad)\n- Fixed Android service mode\n- Fixed UI inconsistencies\n- Fixed Readme download URL. [PR#482](https://github.com/hiddify/hiddify-next/pull/482) by [Ali Afsharzadeh](https://github.com/guoard)\n\n## [0.14.1.dev] - 2024-1-19\n\n### New Features and Improvements\n\n- Redesigned profile options on mobile\n- Improved configuration parser\n- Added export config json in iOS\n- Added iOS URL scheme. [PR#343](https://github.com/hiddify/hiddify-next/pull/343) by [Amir Mohammadi](https://github.com/amirsaam)\n- Added option to reset VPN profile on iOS\n\n### Bug Fixes\n\n- Fixed TLS Tricks causing app crash\n- Fixed connection status on iOS app relaunch\n- Fixed iOS connection stats\n- Fixed infinite subscription traffic\n- Fixed infinite subscription expiry. [PR#334](https://github.com/hiddify/hiddify-next/pull/334) by [Pavel Volkov](https://github.com/pvolkov)\n\n## [0.14.0.dev] - 2024-1-14\n\n### New Features and Improvements\n\n- Published initial iOS beta version on TestFlight\n  - Thanks to contributions from [GFWFighter](https://github.com/GFWFighter) and [Amir Mohammadi](https://github.com/amirsaam)\n  - iOS version is still in heavy development phase and there are known bugs\n- Added Spanish language. [PR#314](https://github.com/hiddify/hiddify-next/pull/314) by [AvatarStark](https://github.com/AvatarStark)\n- Changed Routing Assets page layout, separating assets by type\n- Improved descriptions for some of the options in settings page\n\n### Bug Fixes\n\n- Fixed Deep links on Windows\n- Fixed minor UI bugs\n- Fixed subscription profiles with infinite traffic\n\n## [0.13.6] - 2024-1-7\n\n- First stable 0.13.x release. check changes from 0.13.0.dev to 0.13.5.dev for more details.\n\n## [0.13.5.dev] - 2024-1-6\n\n### New Features and Improvements\n\n- Updated sing-box to version 1.7.8\n- Improved TLS Fragmentation. [PR#12](https://github.com/hiddify/hiddify-sing-box/pull/12) by [Kyōchikutō | キョウチクトウ](https://github.com/kyochikuto)\n- Improved v2ray config parser\n- Added cancel button on new profile modal\n- Changed default Connection Test URL\n\n### Bug Fixes\n\n- Fixed Android service mode\n- Fixed QR code scanner not scanning deep links\n\n## [0.13.4.dev] - 2024-1-4\n\n### New Features and Improvements\n\n- Added update all subscriptions\n  - Force update all subscription profiles regardless of their interval\n- Added basic authorization support\n- Changed app http client, improving experience when fetching profiles, geo assets etc.\n\n### Bug Fixes\n\n- Fixed profile auto update service\n- Fixed localization mistakes in Chinese. [PR#288](https://github.com/hiddify/hiddify-next/pull/288) by [wldjdjsks](https://github.com/huajizhige)\n\n## [0.13.3.dev] - 2024-1-2\n\n### New Features and Improvements\n\n- Added Bypass LAN option (Experimental)\n- Added Connection from LAN option (Experimental)\n- Added DNS Routing option\n- Changed outbound options section to TLS Tricks\n\n### Bug Fixes\n\n- Fixed profile edit bug where you were unable to change existing profile's URL\n- Fixed localization mistakes in Chinese. [PR#287](https://github.com/hiddify/hiddify-next/pull/287) by [Wu Jiahao](https://github.com/wujiahao15)\n\n## [0.13.2.dev] - 2023-12-31\n\n### Bug Fixes\n\n- Fixed db migration bug\n\n## [0.13.1.dev] - 2023-12-31\n\n### New Features and Improvements\n\n- Added experimental feature flag in settings\n- Added notice dialog when connecting with experimental features\n\n### Bug Fixes\n\n- Fixed multiple instance launch on windows\n- Removed auto connect on desktop which caused bugs on auto launch etc.\n- Fixed inlang localization setup\n\n## [0.13.0.dev] - 2023-12-29\n\n### New Features and Improvements\n\n- Added desktop shortcuts\n  - Add profile from clipboard by pressing `CTRL+V` (`CMD+V` on macOS)\n  - Close App window by pressing `CTRL+W` (`CMD+W` on macOS)\n  - Quit App by pressing `CTRL+Q` (`CMD+Q` on macOS)\n  - Open settings page by pressing `CMD+,` on macOS\n- Added Android high refresh rate screen support\n\n### Bug Fixes\n\n- Fixed silent start bug where screen would blink\n- Refactored Window management and system tray, fixing minor bugs\n- Fixed windows portable release again!\n\n## [0.12.3] - 2023-12-28\n\n### New Features and Improvements\n\n- Added version number in window title on desktop\n- Added Afghanistan (af) region with default bypass rules\n\n### Bug Fixes\n\n- Fixed modal bug where config options were unmodifiable. [PR#267](https://github.com/hiddify/hiddify-next/pull/267) by [在7楼](https://github.com/RayWangQvQ)\n- Fixed windows portable release\n\n## [0.12.2] - 2023-12-23\n\n### New Features and Improvements\n\n- Updated Sing-box to Version 1.7.6\n\n### Bug Fixes\n\n- Fixed app log file not including stacktrace\n- Fixed initialization process failing for non-essential dependencies\n- Fixed analytics preferences requiring app restart\n\n## [0.12.1] - 2023-12-21\n\n### Bug Fixes\n\n- Fixed Android service mode\n- Fixed [preferences initialization error on Windows and Linux](https://github.com/flutter/flutter/issues/89211)\n- Fixed incorrect privacy policy URL\n- Bumped Android compile and target SDK version (34)\n\n## [0.12.0] - 2023-12-20\n\n### New Features and Improvements\n\n- Added TLS Tricks (experimental)\n  - Including TLS fragments and Mixed SNI case. This feature might effect performance and battery life\n- Added dynamic notification on Android\n  - Active profile name and transfer speed are now shown in notification\n- Added basic D-pad support for Android TV\n- Added soffchen to recommended geo assets\n- Added option to reset Config Options\n- Improved text input field's accessibility and traversal\n\n### Bug Fixes\n\n- Refactored significant portions of the app\n- Fixed incorrect profile parsing when missing headers\n- Fixed geo assets bug where assets were deactivated\n- Changed default memory limit option on desktop, fixing out of memory bug on macOS\n- Fixed macOS icon\n- Fixed system tray behavior\n- Fixed incorrect casing of locale names\n- Updated sing-box to version 1.7.0\n- Fixed Chinese typography bug (thanks to [betaxab](https://github.com/betaxab))\n- Fixed localization mistakes in Russian. [PR#189](https://github.com/hiddify/hiddify-next/pull/189) by [jomertix](https://github.com/jomertix)\n\n## [0.11.1] - 2023-11-19\n\n### Bug Fixes\n\n- Fixed Android manifest bug.\n\n## [0.11.0] - 2023-11-19\n\n### New Features and Improvements\n\n- Changed Responsive UI Behavior\n  - Now app is responsive on all platforms with appropriate routing setup.\n- Added Simplified Service Modes\n  - Choose between VPN(Tun), System Proxy and Proxy only modes. (System Proxy available on desktop)\n- Added Share Functionality\n  - Share configuration as json(export to clipboard) or share subscription link as QR code.\n- Redesigned System Tray on Desktop\n  - Options have been simplified and a new mode selector and navigation options are added.\n- Added Privilege Checks for VPN(TUN) on Desktop\n- Added Auto Connect on Start\n  - On desktop, app will try to connect to the last used profile on startup. (if last session was not explicitly disconnected by the user)\n- Added AppCast Update Checker\n  - Checking for new versions of the app will use a more reliable approach on all platforms.\n- Added Geo Asset Settings\n  - Update geo assets and use recommended providers\n- Added **winget** Release\n  - Now you're able to install and update Hiddify on Windows using [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/).\n- Added Turkish Translations. [PR#173](https://github.com/hiddify/hiddify-next/pull/173) by [Hasan Karlı](https://github.com/hasankarli)\n- Changed in-app Toasts\n- Updated Core Sing-box Version to 1.7.0\n- Improved Network Reliability While Adding/Updating Subscriptions\n- Improved QR Code Scanner\n\n### Bug Fixes\n\n- Removed **execute config as is** option which caused crashes and confusion for users.\n- Fixed android service revoke and restart.\n- Fixed github release update checker.\n- Fixed translator script. [PR#108](https://github.com/hiddify/hiddify-next/pull/108) by [Hirad Rasoolinejad](https://github.com/Hiiirad)\n- Fixed localization mistakes in Chinese. [PR#113](https://github.com/hiddify/hiddify-next/pull/113) and [PR#123](https://github.com/hiddify/hiddify-next/pull/123) by [Nyar233](https://github.com/Nyar233)\n- Fixed localization mistakes in Chinese Readme. [PR#137](https://github.com/hiddify/hiddify-next/pull/137) by [wldjdjsks](https://github.com/huajizhige)\n- Fixed localization mistakes in Chinese. [PR#138](https://github.com/hiddify/hiddify-next/pull/138) and [PR#165](https://github.com/hiddify/hiddify-next/pull/165) by [wldjdjsks](https://github.com/huajizhige)\n- Fixed localization mistakes in Russian. [PR#155](https://github.com/hiddify/hiddify-next/pull/155), [PR#162](https://github.com/hiddify/hiddify-next/pull/162) and [PR#169](https://github.com/hiddify/hiddify-next/pull/169) by [solokot](https://github.com/solokot)\n- Fixed linux build libs command. [PR#161](https://github.com/hiddify/hiddify-next/pull/161) by [Aloxaf](https://github.com/Aloxaf)\n- Fixed localization mistakes in Russian. [PR#164](https://github.com/hiddify/hiddify-next/pull/164) and [PR#168](https://github.com/hiddify/hiddify-next/pull/168) by [jomertix](https://github.com/jomertix)\n- Fixed localization mistakes in Chinese. [PR#179](https://github.com/hiddify/hiddify-next/pull/179) by [betaxab](https://github.com/betaxab)\n- Fixed localization mistakes in Chinese Readme. [PR#172](https://github.com/hiddify/hiddify-next/pull/172) by [Locas](https://github.com/Locas56227)\n\n## [0.10.0] - 2023-10-27\n\n### New Features and Improvements\n\n- Added Basic region-based routing rules\n  - Based on your selected region (Iran, China or Russia), local ip and domains are bypassed.\n- Redesigned Logs page\n  - Now you're able to pause stream and clear logs. Also logs are delivered more consistently, with less resource consumption.\n- Added tag of selected outbound of selectors to proxies page\n  - Selected outbound tag of selectors like URLTests are now shown in other selectors as well.\n- Added color to delay number in proxies page\n- Memory limit option\n  - Limit sing-box core memory usage.\n- Revamped theme preferences settings\n- Added initial iOS implementation. [PR#98](https://github.com/hiddify/hiddify-next/pull/98) by [GFWFighter](https://github.com/GFWFighter)\n- Added Russian region\n- Added Terms and Conditions and Privacy policy to about page\n\n### Bug Fixes\n\n- Removed reconnection on auto profile updates\n- Fixed filtering logs by level\n- Fixed localization mistakes in Russian. [PR#95](https://github.com/hiddify/hiddify-next/pull/95) by [solokot](https://github.com/solokot)\n- Fixed localization mistakes in Russian. [PR#74](https://github.com/hiddify/hiddify-next/pull/74) by [Elshad Guseynov](https://github.com/lifeindarkside)\n\n[0.16.0.dev]: https://github.com/hiddify/hiddify-next/releases/tag/v0.16.0.dev\n[0.14.1.dev]: https://github.com/hiddify/hiddify-next/releases/tag/v0.14.1.dev\n[0.14.0.dev]: https://github.com/hiddify/hiddify-next/releases/tag/v0.14.0.dev\n[0.13.6]: https://github.com/hiddify/hiddify-next/releases/tag/v0.13.6\n[0.13.5.dev]: https://github.com/hiddify/hiddify-next/releases/tag/v0.13.5.dev\n[0.13.4.dev]: https://github.com/hiddify/hiddify-next/releases/tag/v0.13.4.dev\n[0.13.3.dev]: https://github.com/hiddify/hiddify-next/releases/tag/v0.13.3.dev\n[0.13.2.dev]: https://github.com/hiddify/hiddify-next/releases/tag/v0.13.2.dev\n[0.13.1.dev]: https://github.com/hiddify/hiddify-next/releases/tag/v0.13.1.dev\n[0.13.0.dev]: https://github.com/hiddify/hiddify-next/releases/tag/v0.13.0.dev\n[0.12.3]: https://github.com/hiddify/hiddify-next/releases/tag/v0.12.3\n[0.12.2]: https://github.com/hiddify/hiddify-next/releases/tag/v0.12.2\n[0.12.1]: https://github.com/hiddify/hiddify-next/releases/tag/v0.12.1\n[0.12.0]: https://github.com/hiddify/hiddify-next/releases/tag/v0.12.0\n[0.11.1]: https://github.com/hiddify/hiddify-next/releases/tag/v0.11.1\n[0.11.0]: https://github.com/hiddify/hiddify-next/releases/tag/v0.11.0\n[0.10.0]: https://github.com/hiddify/hiddify-next/releases/tag/v0.10.0\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\nhttps://t.me/hiddify.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nEvery contribution to HiddifyApp is welcome, whether it is reporting a bug, submitting a fix, proposing new features, or just asking a question. To make contributing to HiddifyApp as easy as possible, you will find more details for the development flow in this documentation. [Basic tutorial on how to contribute to HiddifyApp](https://hiddify.com/app/How-to-contribute-to-this-project/)\n\nPlease note, we have a [Code of Conduct](https://github.com/hiddify/hiddify-app/blob/main/CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.\n\n- [Feedback, Issues and Questions](#feedback-issues-and-questions)\n- [Adding new Features](#adding-new-features)\n- [Development](#development)\n  - [Working with the Go Code](#working-with-the-go-code)\n  - [Working with the Flutter Code](#working-with-the-flutter-code)\n    - [Setting up the Environment](#setting-up-the-environment)\n    - [Run Release Build on a Device](#run-release-build-on-a-device)\n- [Release](#release)\n- [Collaboration and Contact Information](#collaboration-and-contact-information)\n\n## Feedback, Issues and Questions\n\nIf you encounter any issue, or you have an idea to improve, please:\n\n- Search through [existing open and closed GitHub Issues](https://github.com/hiddify/hiddify-app/issues) for the answer first. If you find a relevant topic, please comment on the issue.\n- If none of the issues are relevant, please add a new [issue](https://github.com/hiddify/hiddify-app/issues/new/choose) following the templates and provide as much relevant information as possible.\n\n## Adding new Features\n\nWhen contributing a complex change to the Hiddify repository, please discuss the change you wish to make within a GitHub issue with the owners of this repository before making the change.\n\n\n## Development\n\n### Adding Feature / Fix bug in Core:\nPlease follow our [Go Core Development repository](https://github.com/hiddify/hiddify-next-core/main/CONTRIBUTING.m).\n\n### Working with the Flutter Code\nHiddify uses [Flutter](https://flutter.dev), make sure that you have the correct version installed before starting development. You can use the following commands to check your installed version:\n\n```shell\n$ flutter --version\n\n# example response\nFlutter 3.13.4 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 367f9ea16b (4 weeks ago) • 2023-09-12 23:27:53 -0500\nEngine • revision 9064459a8b\nTools • Dart 3.1.2 • DevTools 2.25.0\n```\n\n\nWe recommend using [Visual Studio Code](https://docs.flutter.dev/development/tools/vs-code) extensions for development.\n\n#### Setting up the Environment\n\nWe have extensive use of code generation in the form of [freezed](https://github.com/rrousselGit/freezed), [riverpod](https://github.com/rrousselGit/riverpod), etc. So it's generate these before running the code. Execute the following make commands in order:\nAssuming you have not built the `hiddify-core` and want to use [existing releases](https://github.com/hiddify/hiddify-next-core/releases), you should run the following command (based on your target platform):\n\n\n- `make windows-prepare`\n- `make linux-prepare` \n- `make macos-prepare`\n- `make ios-prepare`\n- `make android-prepare`\n\n\n##### build the `hiddify-core` from source (Optional)\nIf you want to build the `hiddify-core` from source after `make prepare`, use:\n- `make build-windows-libs`\n- `make build-linux-libs` \n- `make build-macos-libs`\n- `make build-ios-libs`\n- `make build-android-libs`\n\n#### Run Release Build on a Device\n\nTo run the release build on a device for testing, we have to get the Device ID first by running the following command:\n\n```shell\n$ flutter devices\n\n# example response\n3 connected devices:\n\n2211143G (mobile) • 35492ae2 • android-arm64  • Android 13 (API 33)\nWindows (desktop) • windows  • windows-x64    • Microsoft Windows [Version 10.0.22000.2482]\nChrome (web)      • chrome   • web-javascript • Google Chrome 117.0.5938.149\n```\n\nThen we can use one of the listed devices and execute the following command to build and run the app on this device:\n\n```shell\nflutter run\n# or\nflutter run --device-id=35492ae2\n```\n\n## Release\n\nWe use [flutter_distributor](https://github.com/leanflutter/flutter_distributor) for packaging. [GitHub action](https://github.com/hiddify/hiddify-app/blob/main/.github/workflows/build.yml) is triggered on every release tag and will create a new GitHub release.\nAfter setting up the environment, use the following make commands to build the release version:\n\n- `make windows-release`\n- `make linux-release`\n- `make macos-release`\n- `make android-release`\n- `make ios-release`\n\n## Collaboration and Contact Information\n\nWe need your collaboration in order to develop this project. If you have experience in these areas, please do not hesitate to contact us.\n\n- Flutter Developing\n- Swift Developing\n- Go Developing\n\n<div align=center>\n</br>\n\n[![Email](https://img.shields.io/badge/Email-contribute@hiddify.com-005FF9?style=flat-square&logo=mail.ru)](mailto:contribute@hiddify.com)\n[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)\n[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)\n[![Twitter](https://img.shields.io/twitter/follow/hiddify_com?color=%231DA1F2&logo=twitter&logoColor=1DA1F2&style=flat-square)](https://twitter.com/intent/follow?screen_name=hiddify_com)\n\n</div>\n"
  },
  {
    "path": "Dockerfile",
    "content": "\n# ==============================================================\n#  ⚠️  USAGE: TRIGGERED BY MAKEFILE\n#  This file is executed via the 'linux-release-docker' command.\n# ==============================================================\n\nFROM ubuntu:22.04\n\nENV DEBIAN_FRONTEND=noninteractive\n\nCOPY linux_deps.list /tmp/linux_deps.list\n\nRUN apt-get update && \\\n    DEPS=$(cat /tmp/linux_deps.list | tr -d '\\r' | sed 's/#.*//g' | xargs) && \\\n    \\\n    apt-get install -y --no-install-recommends $DEPS && \\\n    \\\n    rm -rf /var/lib/apt/lists/* && \\\n    echo \"root ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers\n\nRUN wget -O /usr/local/bin/appimagetool \"https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage\" && \\\n    chmod +x /usr/local/bin/appimagetool\n\nRUN mkdir -p /root/develop && \\\n    git clone https://github.com/flutter/flutter.git -b stable /root/develop/flutter\n\nENV PATH=\"/root/develop/flutter/bin:/root/.pub-cache/bin:${PATH}\"\n\nRUN git config --global --add safe.directory /root/develop/flutter && \\\n    flutter config --no-analytics && \\\n    dart pub global activate fastforge\n\nENV APPIMAGE_EXTRACT_AND_RUN=1\nWORKDIR /app"
  },
  {
    "path": "HISTORY.md",
    "content": "# Changelog\n\n\n## 4.1.2 (2026-03-05)\n\n#### New\n\n* Add doc for dnstt. \n\n\n\n## v4.1.0 (2026-03-05)\n\n#### New\n\n* Add dnstt. \n\n* Add dnstt. \n\n#### Fix\n\n* Test. \n\n* Set ir flag to shir. \n\n* Update linux-appimage-release to copy instead of move Hiddify.AppImage. \n\n* Update linux-prepare target to use linux-amd64-libs. \n\n* Delete bundled libstdc++ for Arch Linux compatibility in AppImage build. \n\n* Resolve shared_preferences conflict between portable and exe formats on Windows. \n\n* Remove timezone_to_country package. \n  _This package caused a black screen and prevented the app from running on the Windows (old) platform._\n\n* Install fastforge and update PATH for Windows build. \n\n* Disable mux and remove geo-related logic. \n\n#### Other\n\n* Merge pull request #1995 from veto9292/main. \n  _black screen and running issue on Windows | shared_preferences conflict between portable and exe on Windows | AppImage running on arch etc… | linux build in ci | add .AppImage release next to the tar | replace ir shir flag | add background for dmg format_\n\n* Feat: replate dmg background image and & improve size and position. \n\n* Test ci. \n\n* Feat: removing country flag from regions text. \n\n* Feat: add raw AppImage support for linux. \n\n* Feat: implement region detection based on timezone and locale. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_ja.md. \n\n* Update README_br.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Centralize the star image. \n  _Added donation support section with links and details._\n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update star history chart in README_ja.md. \n\n* Update README_br.md. \n\n* Fix star history image. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update donation link in README_cn.md. \n\n* Update README_ja.md. \n\n* Update README_br.md. \n\n* Fix donation link and star history chart source. \n  _Updated the donation link and corrected the star history chart image source._\n\n* Update README.md. \n\n* Update qrcode reader lib to support 16kb page. \n\n* Refactor: update project configuration and clean up unused code. \n\n* Merge pull request #1929 from ChabanovX/add-column-exists-check. \n  _Add column exists check_\n\n* Add test in migration that column check works properly. \n\n* Add column checks on 4to5 migration. \n\n* Rename column check for more explicit one. \n\n* Add `column_check` method inside db. \n\n* Merge pull request #1986 from salmanmkc/upgrade-github-actions-node24-general. \n  _Upgrade GitHub Actions to latest versions_\n\n* Merge branch 'main' into upgrade-github-actions-node24-general. \n\n* Merge pull request #1985 from salmanmkc/upgrade-github-actions-node24. \n  _Upgrade GitHub Actions for Node 24 compatibility_\n\n* Upgrade GitHub Actions for Node 24 compatibility. \n\n* Merge pull request #1959 from Enqvy/main. \n  _added tls fragmenting packet option_\n\n* Added manual build (dont meant to be merged) \n\n* Feat: add manual Windows build workflow. \n\n* Added tls fragmenting packet option. \n\n* Merge pull request #1978 from veto9292/sync-slang. \n  _balancer-strategy | remove-mux-geo | sync-slang_\n\n* Feat: update DNS translations for multiple languages. \n\n* Feat: add \"enableFakeDns\" translation for multiple languages. \n\n* Feat: add \"redirectPort\" translations for multiple languages. \n\n* Feat: add \"directPort\" translation to ar. \n\n* Feat: implement balancer strategy configuration and UI integration. \n\n* Feat: add balancer strategy translations for multiple languages. \n\n* Upgrade GitHub Actions to latest versions. \n\n\n\n## v4.0.5 (2026-02-20)\n\n#### Other\n\n* Better support for events. \n\n\n\n## v4.0.4 (2026-02-19)\n\n#### New\n\n* Add endpoint to json editor, \n\n* Add more inbounds(TPROXY, REDIRECT DIRECT) disable pause on desktop. \n\n* Add ios limits and fix workflow. \n\n* Better connection management. \n\n* Add up/down and active profile in android notification. \n\n* Add HiddifyRPC in android. \n\n* Add extra security mode. \n\n* Add fragment button. \n\n* Add remote config support. \n\n* Add better platform management. \n\n* Update the ios interface. \n\n* Add some more checks. \n\n* Add real active tag. \n\n* Upgrade flutter and libs. \n\n* Add quick setting, organize settings, fix reconnect bug, remove profile tab in mobile, use hiddifynextx forfetch profile in xray mode, update flutter. \n\n* Refactor configs to better visualisation. \n\n* Update ci. \n\n* Upgrade dependencies. \n\n* Redesign core interface. \n\n* Add detailed  ipinfo. \n\n* Redisgn ip panel. \n\n* Add auto start for mac. \n\n* Add support for auto start in macos. \n\n* Add org flag. \n\n#### Changes\n\n* Remove platform widget. \n\n* Disable HTTP subscribe link as they create great issue. \n\n* Some refactor. \n\n#### Fix\n\n* Issue in profile editor, better error display. \n\n* Issues. \n\n* Update build matrix to include Android and Windows targets. \n\n* Version issue. \n\n* Update step name for Flutter setup in build workflow. \n\n* Correct syntax for conditional in Flutter setup for arm64. \n\n* Update Flutter setup condition for non-linux-arm64 platforms. \n\n* Bug. \n\n* Prepare. \n\n* Remove unused variables for zip file path in windows release process. \n\n* Update app icon type to use stock icon for consistency. \n\n* Update AppImage build command to disable appstream and correct file move. \n\n* Downgrade `sentry_flutter` to remove jni dependency (avoids forced JDK installation) \n\n* Update AppImage post-processing steps and improve Docker volume mounts. \n\n* Update build targets for Android to include AAB format and fix windows-install-deps. \n\n* Sticky notif. \n\n* Update macOS version from 13 to 15 in build workflow. \n\n* Replace flutter_distributor with fastforge for macOS and iOS packaging. \n\n* Improve sh compatibility. \n\n* Change variable assignment from := to = for consistency in Makefile. \n\n* Update sed command definition for Windows compatibility. \n\n* Workflow. \n\n* Workflow. \n\n* Persistent data after uninstalling Windows EXE. \n\n* Issue in ios and imrpove stablity. \n\n* Android bug. \n\n* Notification AND VPN MODE  in android. \n\n* Font json editor. \n\n* Ios. \n\n* Per app proxy. \n\n* Tile service. \n\n* Windows build issue. \n\n* Typo. \n\n* Bugs and improvement. \n\n* Select tag bug. \n\n* Makefile path issue in Windows OS. \n\n* Linux installation. \n\n* Ios build. \n\n* Bug. \n\n* Interface change and warp crash. \n\n* Quicktile bug and update to singbox 10.3. \n\n* Bug? \n\n* Macos. \n\n* Macos build. \n\n* Emoji in profile and proxies. \n\n* No commit message. \n\n* Ios. \n\n* Ios interface. \n\n* Name changing. \n\n* Typos for ios. \n\n#### Other\n\n* Merge branch 'new-design-v2' \n\n* Fix arm build. \n\n* Refactor: update InboundOptions fields and translations for direct and redirect ports. \n\n* Add naive. \n\n* Fix. \n\n* Update. \n\n* Merge pull request #36 from veto9292/new-design-v2. \n  _CI_\n\n* Feat: add supported MIME types for app links on Linux AppImage. \n\n* Refactor: rename macOS and iOS install dependencies targets and update activation command. \n\n* Speedup ci. \n\n* Merge. \n\n* Feat: enhance logging in Makefile with color-coded output. \n\n* Feat: add post-processing for Windows portable zip release. \n\n* Fix CI: \"copy to out\" for \"windows\" \n\n* Fix CI: Copy to out Windows. \n\n* Fix CI: skipping chmod for tar. \n\n* Fix CI: NDK version. \n\n* Fix CI: linux AppImage build. \n\n* Fix CI: linxu AppImage build. \n\n* If: REQUIRED_VER in Makefile. \n\n* Update: hiddify-core.diff. \n\n* Generate: proto files. \n\n* Add protoc_plugin activation to linux-install-deps. \n\n* Fix CI \"Build platform\" \n\n* Fix CI \"Setup dependencies\" \n\n* Fix connection change issue and more and more optimisation. \n\n* Update psiphon add new dns manager, fix ios ipv6 issue. \n\n* Add proxy usage bytes, psiphon and more and more. \n\n* New balancer approach. \n\n* Better proxy,fix ios. \n\n* New add amnezia, wiregaurd raw config, wiregaurd noise. \n\n* Add inner proxy link, add debounce. \n\n* Revert makefile. \n\n* Fixes and improvements. \n\n* Update ios. \n\n* Better android vpn service start and fix bugs. \n\n* Update android codes to latest singbox. \n\n* Update macos. \n\n* Update fultter. \n\n* Merge. \n\n* Merge pull request #34 from veto9292/small-fix/fastforge-apk-release. \n  _fastforge migration (android, windows, linux) | storage and path | format codebase | upgrade flutter | flutter discontinued package | dart style | restore window state on Desktops | fastforge release-apk (small fix)_\n\n* Merge remote-tracking branch 'h/new-design-v2' into small-fix/fastforge-apk-release. \n\n* Remove forgotten test parameter. \n\n* Implement window state persistence and position validation - Added `saveWindowState` to persist window size, position, and maximized state. - Added `initWindowState` to restore window bounds with safety checks. - Implemented `checkWindowVisibility` to prevent off-screen startup in multi-monitor setups. \n\n* Calling saveWindowState in onWindow (Resized, Moved, Maximize, Unmaximize) methods. \n\n* Add window (position, size, maximize) preferences to general_preferences. \n\n* Relocate 'window silent start' logic to window_notifier.dart. \n\n* Installing 'screen_retriever' package. \n\n* Format .dart files. \n\n* Fix dart formatter width. \n\n* Replace flutter_markdown with flutter_markdown_plus and update version in pubspec.yaml; adjust pubspec.lock accordingly. \n\n* Upgrade Flutter and SDK versions; update NDK and Kotlin plugin versions; refresh package dependencies in pubspec.lock. \n\n* Added 'Hiddify Dev Windows Portable' config to launch.json for easier testing and development of the Windows Portable version. \n\n* Migrate release builds to fastforge and overhaul Linux/Docker systems. \n  _This major update migrates all release pipelines (except macOS/iOS) to fastforge and completely overhauls the Linux build process.\n\n### Migration to fastforge\n- Migrated all release commands to fastforge for consistency and better management.\n- Replaced legacy build scripts with fastforge commands for Windows, Linux, and Android.\n- Android APK/AAB builds now utilize fastforge instead of raw commands.\n\n### Linux Build Refactor\n- Introduced `linux-release-docker` command.\n- Updated `linux-release-appimage` with new post-build scripts.\n- Implemented `Linux Install Deps` script:\n  - Automatically prepares the environment (Ubuntu/WSL).\n  - Clones Flutter SDK from GitHub (stable branch) instead of downloading the archive.\n  - Checks out the specific Flutter version defined in `pubspec.yaml` using `Linux Flutter Sync`.\n  - Installs required dependencies from `linux_deps.list`.\n- Rewrote AppImage packaging:\n  - Manually constructs the AppImage directory structure.\n  - Injects a custom `AppRun` script.\n  - Implements a self-contained portable data structure:\n    - Creates `hiddify.appimage.home` directory alongside the AppImage.\n    - Stores configuration and user data within this directory to keep the system clean.\n\n### Dockerized Build System\n- Added `linux-release-docker` for building Linux artifacts without a local Linux environment.\n- Caches Flutter SDK and Pub packages via Docker volumes to speed up subsequent builds.\n- Outputs artifacts to `dist_docker` directory on the host machine.\n\n### Windows Improvements\n- Updated `windows-release-zip` to include the `portable` environment variable for portable builds.\n\n### Other Changes\n- Added `linux_deps.list` to centralize dependency management.\n- Added `linux-flutter-sync` to `linux-prepare` command.\n- Introduced `LINUX_DEPS` variable to extract package list from `linux_deps.list`.\n- Introduced `REQUIRED_VER` variable to extract Flutter version from `pubspec.yaml`.\n- Added `linux-flutter-sync` command to ensure the installed Flutter version matches `pubspec.yaml`._\n\n* - Update getDatabaseDirectory to support portable mode based on the `` env var. - Create 'hiddify_portable_data' in the app directory if running in portable mode. - Add 'checkDirectoryAccess' to verify read/write permissions for the portable data folder. - Fallback to the default system path if write access to the portable directory is denied. \n\n* - Add  environment variable to identify the Windows portable version - This variable is set during the 'windows-release-zip' build process. \n\n* On Linux, left-clicking the tray icon opens the context menu instead of triggering `onTrayIconMouseDown`. Added a \"Dashboard\" menu item as a workaround to allow users to open the app window. \n\n* - Ignore MSIX self-signed keys to prevent accidental commit of secrets - Add dist_docker directory (Docker build output) to ignored paths. \n\n* - Enable Linux artifact building without requiring a local Linux environment (e.g., WSL or native Ubuntu) - Designed to be executed via the 'linux-release-docker' command in the Makefile. \n\n* Add some comments. \n\n* Pin Flutter SDK version and register new icon asset - Explicitly define Flutter SDK version in pubspec.yaml for consistency. - Note: This version is critical as it is parsed by Makefile and Dockerfile to setup the build environment. - Add 'ic_launcher_border.png' to the assets list. \n\n* Created a dedicated list file for Linux dependencies and integrated it into both Dockerfile and Makefile. \n\n* Switched to C++17 to ensure better compatibility with modern libraries and potential future dependencies. \n\n* Add some comments. \n\n* Update AppImage configuration in make_config.yaml - Remove app_run_file parameter (AppRun is now injected post-build) - Fix icon path - Update AppRun: Add install_integration to setup icons and create local .desktop entry with correct Exec path - Ensure index.theme creation if missing. \n\n* Update deb configuration in make_config.yaml - Add comments for supported_mime_type parameter - Add user data cleanup script to postuninstall_scripts - Update postinstall_scripts to set StartupWMClass to app.hiddify.com and remove conflicting hiddify.desktop from .local. \n\n* We decided to remove RPM packaging for the following reasons: - Flutter officially supports Debian-based systems only. - Persistent issues with dependency linking. - High maintenance overhead (requires Fedora environment setup). - Successful builds do not guarantee runtime stability on Red Hat-based systems. \n\n* Update MSIX config in make_config.yaml - Complete the list of supported languages - Add commented-out parameters for self-signed certificate. \n\n* Update exe configuration in make_config.yaml - Update publisher_url from hiddify-next to hiddify-app - Fix app_icon.ico path - Complete list of setup locales - Remove redundant 'executable_name' and 'output_base_file_name' parameters. \n\n* Synchronizing main_prod.dart with main.dart. \n\n* Removing \"distribute_options.yaml\" because we are using \"fastforge package\" command and \"distribute_options.yaml\" is realated to \"fastforge release\" command. \n\n* Fixing riverpod issue with adding \"agreed\" parameter to recurcise method (applyConfigOption) and using this paramter instead of reading provider state in next call. \n\n* Small fix/ using _prefs instead of ref.read. \n\n* \"not important\" formating text for better understaning changes in next commits. \n\n* Renaming db name and import path. \n\n* Removing \"DbV1\" provider and renamign \"DbV2\" to \"Db\" \n\n* Renaming \"db_v2\" to \"db\" and using this \"db\" as main database by adding onUpgrade and increasing \"schemaVersion\" to 5 and fixing directory issue by adding \"native\" parameter to \"driftDatabase\" method. \n\n* Generation new steps.dart for new database. \n\n* Removing migration helper for copying data from \"db_v1\" to \"db_v2\" \n\n* \"not important\" formating text for better understaning changes in next commit. \n\n* Updating \"test\\drift\". auto generated with drift_dev. \n\n* Moving \"db_v1\" schemas to \"schemas\\db\" and generation \"schema_v5\" \n\n* Removing \"db_v2\" and rename \"db_v1\" to \"db\" \n\n* Merge branch 'new-design-v2' into remove/geo-assets. \n\n* Update release files. \n\n* Improve notification AND VPN MODE  in android. \n\n* Merge pull request #30 from veto9292/remove/geo-assets. \n  _Remove/geo assets_\n\n* Removing \"get-geo-assets\" target from \"Makefile\" \n\n* Removing \"MissingGeoAssets\" from \"ConnectionFailure\" \n\n* Moving \"GeoAssetType\" to \"db_v1\" \n\n* Removing translations related to \"geo-assets\" \n\n* Removing lib\\features\\geo_asset. \n\n* Merge pull request #29 from veto9292/fix/reported-issues-v1. \n  _Fix/reported issues v1_\n\n* Update/test file. auto generated with drift_dev. \n\n* Update/ using DbV2 instead of AppDatabase. \n\n* Comment geo asset data 'mapper | source' \n\n* New/ run db migration from v1 to v2 in bootstrap. \n\n* New/ db migration helper from v1 to v2. \n\n* Improve/ renaming. add dbV2 provider. \n\n* New/creating db_v2 that equals db_v1 v5 schema. downgrade db_v1 to v4 schema. merging tables logics with db logics. \n\n* Update/schemas move db schema to new location and regenerate db_v1 schema_v4. \n\n* Update/build.yaml add 'db v2' path to drift_dev. changing drift_dev path (schema_dir, db_v1). \n\n* Fix/ with the new version of go_router, there is no need to add a navigatorKey to StatefulShellBranch to preserve its state. \n\n* Small fix/warnings \"unnecessary_underscores\" \n\n* Fix/ fixing prevent closing branch issue... removing \"back_button_interceptor\" and \"prevent_closing_branch.dart\"... upgrading go_router to 16.2.4 and using \"PopScope\" instead of \"back_button_interceptor\" package. \n\n* Small fix/ add: Warp, Fragment, and Padding icons in Settings option. Change the icon for the 'Padding-Size' option. \n\n* Update macos. \n\n* Merge pull request #28 from veto9292/chore/upgrade-flutter-version. \n  _Chore/upgrade flutter version_\n\n* Resolve dependency conflicts for Flutter upgrade. \n  _Upgraded development dependencies to support the Flutter SDK migration\nfrom version 3.32.5 to 3.35.4 and resolve version solving failures._\n\n* Merge pull request #27 from veto9292/feature/i18n-refactor. \n  _Feature/i18n refactor_\n\n* Small fix/ update pages.profiles.updateSub to updateSubscriptions. \"Update connection profiles\" => \"Update subscriptions\" \n\n* Refactor(localization): Sync codebase with new i18n structure. \n  _This commit adapts the application's source code to the newly restructured and renamed translation files. It ensures all UI text is correctly referenced and improves how feedback messages are handled.\n\n- Updated all translation keys throughout the source code to align with the new nested structure.\n- Added and corrected translations for user-facing toasts to provide appropriate success and failure feedback (e.g., for import/export actions).\n- Implemented logic to display newly added translations where they were previously missing._\n\n* Refactor(i18n): Restructure and clean up localization files. \n  _- Restructured keys into a feature-based nested format for better maintainability.\n- Renamed files from strings_[locale] to [locale].i18n.json to fix tooling warnings.\n- Removed the unused Sorani Kurdish (ckb) locale._\n\n* New/ auto generated by \"dart run slang configure\" \n\n* Upgrade/ slang(4.4.0 to 4.5.1) slang_flutter(4.4.0 to 4.8.0) \n\n* Update workflow. \n\n* Merge branch 'new-design-v2' of ssh://github.com/hiddify/hiddify-next-ios into new-design-v2. \n\n* Merge pull request #26 from veto9292/fix/reported-issues. \n  _Fix/reported issues_\n\n* Small fix/ profile_parser_test file was updated based on the changes in 'ProfileParser' \n\n* Update/ Improved UI/UX and aligned it with the manual section of the 'Add Profile' modal. \n\n* Update/ using loadingState instead of (save, update, delete & isBusy). ProfileDetailsPage is now used only for editing. The profile_details_notifier was completely rewritten, and the logic for applying and saving changes has been greatly simplified. \n\n* Update/ using Material icons instead of FluentIcons. \n\n* Update/ UI improvment. \n\n* Delete profile_local_override.dart. \n\n* Small fix/ using Material Icons instead of Cupertino Icons. \n\n* Update, fix/ fixed 'Free' profiles not updating and made minor changes to align with AddProfileNotifier.addManual. \n\n* Update, fix/ using Material icons instead of FluentIcons. Fixed the bottom sheet not closing when showing profileDetails. \n\n* Update/ rename method and use url to upsert. \n\n* Update/ rename methods. \n\n* Small fix. \n\n* Update/ moved part of the deleteProfile logic to ProfileDataSource. replaced the abortConnection method with toggleConnection. \n\n* Update/ updated AddProfileNotifier methods. added a Tile for isAutoUpdateDisable and to display the auto-update status. made minor changes to the Add button logic. \n\n* Update/ prevented error display on HTTP request cancellation. removed commented-out code. separated profile addition methods (addClipboard, addManual). rewrote the add method based on profileRepository changes and removed the renaming logic. canceled the request when AddProfileNotifier is disposed. \n\n* Update/ added profileParser and removed httpClient from the profileRepository's input parameters, adding profileParser as the new input parameter. \n\n* Update/ removed the local-override logic that was previously added to watchActiveProfile for preserving userOverride. added renaming logic to the insert operation; if a name is duplicated, random numbers are appended to the end (using getByName) so the user can differentiate. added logic to check for a profile's existence before editing. to manage the active profile during deletion, the isActive parameter is received. If the profile being deleted is active, another profile is selected as active after its removal. \n\n* Update/ passing the profile object to connect and reconnect. \n\n* Update/ parameters of the connect and reconnect methods were changed for simplicity. Commented-out code was removed. applyConfigOption was rewritten to align with the profileOverride changes. \n\n* Refactor/ deleted methods include (getByName, addByUrl, updateContent, addByContent, updateSubscription, add, patch, fetch). upsertRemote: Handles both creation and updating of remote profiles from a single entry point. It checks for an existing profile via URL to prevent duplicates. addLocal: Allows for creating profiles directly from local string content. offlineUpdate: Enables offline modifications by re-parsing the profile with new content while preserving existing headers. validateConfig: The logic has been updated to correctly handle and apply configuration overrides, which were previously ignored. removed the 'http_client' dependency from the repository. This responsibility has been moved to the 'profile_parser' to better separate concerns. a previously public field has been made private. the 'setActive' and 'deleteById' methods have been formally defined in the abstract interface. \n\n* Refactor/ converts the static 'ProfileParser' into a service class with access to Riverpod's 'ref'. adds 'addRemote', 'addLocal', 'updateRemote', and 'offlineUpdate' methods using 'fpdart'. moves profile download logic from 'profile_repository' to 'ProfileParser' and rewrites it with 'fpdart'. adds error handling for user-cancelled downloads. reads 'useXrayCoreWhenPossible' directly from 'ref' instead of passing all settings. changes the 'parse' method's input to 'ProfileEntity', simplifying the return logic with 'profile.map'. updates the name parser hierarchy to use the link protocol as a fallback. adds logic to disable profile auto-updates via user override. \n\n* Remove/ move 'protocol' method from 'link_parsers' to 'profile_parser' \n\n* Update/ removed 'toEntry' and 'subInfoPatch' methods from 'ProfileEntity'. added 'toInsertEntry' and 'toUpdateEntry' methods and replaced 'map' with 'switch'. added 'userOverride' and 'populatedHeaders' to the 'toEntity' method and renamed 'testUrl' to 'profileOverride'. \n\n* Update/ renamed 'testUrl' to 'profileOverride'. added a default value of 'Duration.zero' to 'updateInterval'. add/ added 'userOverride' and 'populatedHeaders' to the remote and local models. added a 'UserOverride' model with a version structure to ensure backward compatibility in the future. added isAutoUpdateDisable with default(false) to 'userOverride' \n\n* Update/ changes to 'ConfigOptionRepository' class: made 'getConfigOptions' private. renamed method 'getFullSingboxConfigOption' to 'fullOptions'. added method 'fullOptionsOverrided', which applies 'profileOverride' to the 'config options' before they're sent. improved error handling with 'fpdart'. \n\n* Update/ add 'ConfigOptionFailure' to 'ProfileFailure.invalidConfig' parameters to easily convert 'ConfigOptionFailure' to 'ProfileFailure'. add 'cancelByUser' for when an HTTP request is cancelled by the user(this helps to distinguish the error and prevent its display) \n\n* Update/ add 'ConfigOptionFailure' to 'ConnectionFailure.invalidConfigOption' parameters to easily convert 'ConfigOptionFailure' to 'ConnectionFailure' \n\n* Update/ schema_v5 test file(auto generated by drift_dev) \n\n* Delete/ old drift test files. \n\n* Update/ adding columns(userOverride, populatedHeaders) to profile table in db. renaming test_url column to profileOverride. app_database.steps.dart & drift_schema_v5.json is auto generated by drift_dev. \n\n* Update/ en, fa translations. add(general.auto, profile.add.disableAutoUpdate, failure.profiles.canceledByUser). update(profile.detailsForm.updateInterval). \n\n* Update/ supporting deselected state for Per-app porxy apps in UI. \n\n* Update/ bump target/compileSdk to 36; align AGP/Kotlin. \n\n* Fix/ deprecated warning. \n\n* New/ apps auto selection modal. features: auto update, reset to default, changing update interval, enable or disable auto-selection, perform now. \n\n* Update/ using db for managing state. moving and removing providers. adding shareOnGithub to notifier. removing installed apps notifier provider. \n\n* Update/ notifying user and disabling auto-selection after a region change. \n\n* New/ activating and managing the per-app proxy auto-selection service. \n\n* New/ managing loading for asynchronous operations. \n\n* New/ this service is initialized in app.dart and is responsible for auto-update functionality for auto-selection feature. It is also in charge of updating the active list in prefs. \n\n* Update/ new sort logic with 4 priority. using hooks for getting and managing installed apps. auto sort feature. adding scroll to top feature. adding loading for share to all. adding FAB for auto selection modal. \n\n* Fix/ AppProxyMode not found error. \n\n* New/ AppProxyDao is for interacting with the AppProxyEntries table. \n\n* Update/ change return types from List to Set. removing share method from repository. renaming methods. using AppProxyMode instead of PerAppProxyMode. \n\n* New/ appProxyDataSourceProvider. \n\n* New/remove/ adding AppPackageInfo as a replacement for InstalledPackageInfo to store installed apps. \n\n* New/ per_app_proxy_backup model is used for import & export. \n\n* New/ adding AppProxyMode alongside PerAppProxyMode; the difference is the lack of an off state. \n\n* New/ PkgFlag, managing bit-flags for selected apps in per-app-proxy. \n\n* Update/ import UI and logic for add_profile_modal.dart. \n\n* New/update/ moving per_app_proxy_include_list & per_app_proxy_exclude_list to Preferences. adding auto_apps_selection_update_interval & auto_apps_selection_last_update. renaming autoSelectionAppsRegion to autoAppsSelectionRegion. \n\n* New/ drift migration test files (generated by drift_dev) \n\n* Add/update/fix/remove/ adding AppProxyEntries to db tables, fixing AppDatabase constructor, adding from4To5 and increasing schemaVersion to 5, generating drit_schema_v5 with drift_dev, removing database_connection.dart. \n\n* New/ app_database.steps.dart generated by drift_dev. \n\n* Move file/ moving drift schema from schemas\\ to schemas\\app_database. \n\n* New/ adding AppProxyEntries to db tables. \n\n* Fix/ adding translationsProvider to bootstrap. \n\n* Update/ en, fa translations new: autoSelection(performNow, resetToDefault) network.share(alreadyInAuto) update: network(clearSelection) autoSelection(dialogTitle, msg, success, regionNotFound) network.share(emptyList) \n\n* Update/ adding database and schema dir to drift_dev in build.yaml. \n\n* New/ drift migration test files (generated by drift_dev) \n\n* Adding method to RuleEnum for getting index of key. \n\n* Updating en, fa translations. Using \" instead of ( for autoSelection.dialogTitle. Adding positiveBtnTxt to per-app proxy share dialog. \n\n* Improving error management and preventing possible crash for auto_selection_repository. \n\n* Changing text \"Share\" to \"Share To All\" in per-app proxy. \n\n* Displaying a notification dialog before sharing selected apps. \n\n* Updation en, fa translations Adding title, dialogTitle, msg to settings.network.share. \n\n* Merge branch 'fix/reported-issues' of https://github.com/veto9292/hiddify-next-ios into fix/reported-issues. \n\n* Suggesting auto selection apps when changing region. \n\n* Improving naming and logic in 'per_app_proxy_page.dart' and adding auto selection, share, import/export to the menu, sorting selected items, using menu for mode selection, setting 'hideSystemApps' with a chip. \n\n* Improving naming and logic in 'per_app_proxy_notifier.dart' and adding methods (share, clearSelection, autoSelection, export clipboard/file, import clipboard/file). \n\n* Add auto selection data provider and repository To get the list of proxy/bypass applications from GitHub and share the selected list as an issue. \n\n* Removing per_app_proxy_data_providers & per_app_proxy_repository Instead, the `installed_apps` package is used. \n\n* Using MenuAnchor instead of PopupMenuButton in settings_page. \n\n* Updating en & fa translations adding (import, export, share) to general adding (autoSelection, share, import, export) to setting.network. \n\n* Adding 'auto_selection_apps_region' to 'general_preferences.dart' \n\n* Changing the order of buttons in ConfirmationDialog. \n\n* Renaming 'okText' to 'positiveBtnTxt' for confirmation dialog. \n\n* Merge pull request #25 from veto9292/fix/reported-issues. \n  _Fix/reported issues_\n\n* Merge branch 'new-design-v2' into fix/reported-issues. \n\n* Better log page, upgrade to flutter 3.32.4. \n\n* Merge branch 'new-design-v2' of ssh://github.com/hiddify/hiddify-next-ios into new-design-v2. \n\n* Merge pull request #24 from veto9292/fix/reported-issues. \n  _Fix/reported issues_\n\n* Merge. \n\n* Merge branch 'new-design-v2' of ssh://github.com/hiddify/hiddify-next-ios into new-design-v2. \n\n* Merge branch 'new-design-v2' of ssh://github.com/hiddify/hiddify-next-ios into new-design-v2. \n\n* Update flutter. \n\n* Fixing setSkipTaskbar in macOS and renaming WindowNotifier methods. \n\n* Updating  window_manager & tray_manager packages. \n\n* Remove experimental feature references from settings pages and related files. \n\n* Renaming 'inbound_options.dart' to 'inbound_options_page.dart' \n\n* Using 'profileDataSourceProvider' instead of 'profileRepositoryProvider' in 'active_profile_notifier.dart' to prevent redundant builds. \n\n* Removing 'distinct()' from 'profile_repository.dart' and adding it to 'profile_data_source.dart' to prevent emitting extra events. \n\n* Removing 'async' from 'SingConfigOption' and using watch instead of read. \n\n* Removing extra file. \n\n* Preventing redundant builds in 'routing_config_notifier.dart' when the last profile is deleted and 'Breakpoint' is 'isMobile'. \n\n* Fixing SideBarStatsOverview issue. \n\n* Removing 'flutter_adaptive_scaffold' and using Flutter SDK. Updating logic related to 'Breakpoint'. \n\n* Using 'Breakpoint' instead of Breakpoints in 'flutter_adaptive_scaffold' method. \n\n* Using 'Breakpoint' instead of Breakpoints in 'flutter_adaptive_scaffold' method. \n\n* Removing 'branchNavKey' and using new 'Breakpoint' logic instead of 'isSmallActive'. \n\n* Updating 'ActiveBreakpointNotifier' update logic. \n\n* Renaming 'is_small_active' to 'active_breakpoint_notifier'. Adding 'Breakpoint' class for storing breakpoint and helper methods for detecting the active breakpoint. Changing 'ActiveBreakpointNotifier' output to 'Breakpoint' and adding a provider named 'isMobileBreakpoint'. \n\n* Commenting out 'PopupCountNotifier'. \n\n* Using 'rootNavKey' instead of 'branchNavKey'. \n\n* Using 'rootNavKey' instead of 'branchNavKey' and commenting out 'PopupCountNotifier' methods. \n\n* Removing flutter_adaptive_scaffold from pubspec. \n\n* Updating Flutter to 3.32.5 and upgrading pub. Updating intl to 0.20.2. Solving pub get issue by adding humanizer version 3.0.1 instead of getting from GitHub. \n\n* Organizing per app proxy page. \n\n* Fix import and use read instead of watch. \n\n* Unifying the status bar and system navigation bar color with the scaffold color. \n\n* Fixing profile disappearance (when the profile being updated is selected as the active profile) \n\n* Improving popup hiding nav bar animation(temporary) \n\n* Fixing Segmented Button UI in Quick Setting Modal. \n\n* Fixing routing config rebuilding when deleting profile. \n\n* Fixing bottom sheet overlapping with keyboard. \n\n* Fix warp secure lable for connection button. \n\n* Improve warp generation toast, merge warp loading logic in warp_option_notifier.dart. \n\n* Improve out animation for bottom sheet when popup is showing. \n\n* Fix toast direction, removing context from \"in_app_notification_controller\", add dismissAll() to _show. \n\n* Removing toast handler from \"profiles_modal\" and \"profiles_page\", move toast handler for success or failure profiles update to \"profiles_update_notifier\" \n\n* Preventing redundant builds by removing duplicate events from the stream and using \"hasAnyProfileProvider\" in routing_config_notifier.dart. \n\n* Adding ToastificationWrapper for showing toast without context. \n\n* Renaming and organizing files and classes related to \"Profiles\" \n\n* Merge pull request #23 from veto9292/fix/reported-issues. \n  _Fix/reported issues_\n\n* Move popup_count_notifier from dialog_notifier to dedicated file. \n\n* Rename riverpod_listenable to refresh_listenable. \n\n* Remove disabled parameter from SideBarStatsOverview. \n\n* Removing unnecessary files. \n\n* Remove CustomAlertDialog from alerts.dart (move it to the dialog/widgets) \n\n* Using dialog notifier, using new global key. \n\n* Fix bottom sheet typo, rename root nav key. \n\n* Merge config options with settings feature. \n\n* Rewriting all items in settings, adding icons, organizing folder structure and files. \n\n* Rename settings_repository to battery_optimization_repository. \n\n* Fix imports. \n\n* Fix imports. \n\n* Fix imports. \n\n* Move WarpLicenseDialog.dart to dialog\\widgets, fixing import warning dialog_notifier.dart. \n\n* Move quick settings modal to botto_sheets\\widgets, fixing import warning in bottom_sheets_notifier.dart. \n\n* Show toast instead of dialog for warp success generation. \n\n* Fix platform_settings_notifier async issue, applying name changes, manage loading state, rewriting platform_settings_tiles and fixing loading. \n\n* Rename settings_repository to battery_optimization_repository rename settings_data_providers to battery optimization_provider move files. \n\n* Using dialog notifier, moving SettingTextDialog to dialog/widgets. \n\n* Using dialog notifier moving SettingsRadioDialog to dialog/widgets. \n\n* Using dialog notifier, moving setting_checkbox to dialog/widgets. \n\n* Using dialog notifier. \n\n* Using dialog notifier. \n\n* Using dialog notifier. \n\n* Moving proxy-info dialog to the dialog notifier, using goNamed. \n\n* Fix bottom sheet typo, using goNamed, using dialog notifier. \n\n* Using dialog notifier, add ref to _launchUrlWithCheck method. \n\n* Renaming ProfilesOverviewPage to ProfilesPage, fix bottom sheet typo, use context.goNamed, removing autoImplyLeading \"becase routing is fixed\" \n\n* Using dialog notifier. \n\n* Using dialog notifier. \n\n* Fix imports. \n\n* Fix ref and imports. \n\n* Using dialog notifier. \n\n* Using dialog notifier. \n\n* Set return type for dialog. \n\n* Renaming LogsOverviewPage to LogsPage, use AppBar instead NestedScrollView. \n\n* Add const to constructor, romoving SafeArea to solve UI issue,  preventing operations during loading. \n\n* Commenting unused widget, fix bottom sheet typo. \n\n* Remove showAddProfile and url parameter from HomePage this logic is moved to the redirect in routing-config-notifier. \n\n* Using dialog notififer, remove showExperimentalNotice \"moved to dialog notifier\" \n\n* Using dialog notifier, move showExperimenNotice logic to dialog-notifier. \n\n* Fix import. \n\n* Using dialog notifier, changing icons, dynamic icon for theme mode. \n\n* Fix imports, using dialog notifier. \n\n* Fix imports, set return type for showing dialog. \n\n* Fix imports. \n\n* Move new_version_dialog.dart to lib\\core\\router\\dialog\\widgets. \n\n* Fix ref warning. \n\n* Move about_page.dart to lib\\features\\about\\widget. \n\n* PreventClosingApp in routing_config_notifier.dart is used for preventing the branch from closing. It transfers the user to Home route after preventing the closing. \n\n* Is_small_active.dart IsSmallActive is true when the breakpoint is in the small range, and false otherwise. app.dart Updating the router provider. Assigning a value to IsSmallActive. useEffect has been used for improving performance. \n\n* CustomTransition is used for adding animation to pages in routing_config_notifier.dart. The purpose of creating this class is to prevent boilerplate code. \n\n* RoutingConfigNotifier returns a RoutingConfig which is used for updating rConfig in GoRouterNotifier. The structure of routes is defined in RoutingConfigNotifier. The redirect method is defined in RoutingConfigNotifier. By listening to other providers, a new list of routes can be returned dynamically. \n\n* An instance of RefreshListenable is passed to refreshListenable in GoRouterNotifier. If the notifyListeners method is called, the anonymous redirect function in RoutingConfig is executed. By using ref, a specific provider is listened to, and if it changes, the provider's value is stored globally in a variable, and notifyListeners is called. \n\n* GoRouterNotifier creates the GoRouter instance that is passed to MaterialApp.router. It holds a RoutingConfig within itself, which gets its value updated by listening to RoutingConfigNotifier. With changes to RoutingConfig, the app's routes will change dynamically. \n\n* Move dialogs from project to lib\\core\\router\\dialog\\widgets fix navigation logic for dialogs add translations. \n\n* Adding the _show method for managing the number of popups, reducing boilerplate code, and managing context move all dialog to this notifier explicitly specifying a return type. \n\n* Fix typo(buttom to bottom), adding the _show method for managing the number of popups, reducing boilerplate code, and managing context. \n\n* Fix import, fix Ref warning, remove \"error dialog\", changing context that are used for displaying toast. \n\n* Fix warning/ Ref, import, async. \n\n* My_adaptive_layout.dart is a shell for the main navigator which is used inside StatefulShellRoute in go_router shell_route_action.dart, which stores information related to each action in my_adaptive_layout.dart. \n\n* Move my_app_links.dart to lib\\core\\router\\deep_linking. \n\n* Remove/ app_router.dart, router.dart, routes.dart. \n\n* New/ move url_protocol to lib\\core\\router\\deep_linking\\url_protocol. \n\n* Update/ translations(en, fa) general.save general.close unknownDomains.title unknownDomains.youAreAboutToVisit unknownDomains.thisWebsiteIsNotInOurTrustedList. \n\n* Add/ back_button_interceptor package to pubspec, update AndroidManifest (platform-specific setting) \n\n* Update go_router and flutter_adaptive_scaffold packages, remove go_router_builder package. \n\n* New/ show \"qr dialog\" for \"allow connection from LAN\" \n\n* Improve/ add comment for network_info_plus package. \n\n* Add/ network_info_plus package. \n\n* Small fix/ profile tile radius issue. \n\n* New/ merge warp license aggrement, seprate warp options logic, move license agreement to connection button and connection repo and more... \n\n* New/ add missing warp license to connection_failure. \n\n* Small fix/ warnings & rename testUrl to override. \n\n* Improve/ add showWarpLicense & showWarpConfig dialog to dialog_notifier. \n\n* Add translations/ failure.warp.missingLicense & missingLicenseMsg. \n\n* Small fix/ rename testUrl to override. \n\n* Fix/ warp license agreeement focus, rename intro page const. \n\n* Improve/ focus logic for intro page. \n\n* Fix/ adding a timer for syncing status with changes outside the app. \n\n* Small fix/ add gap to app bar actions. \n\n* Small fix/ add gap to app bar action. \n\n* Fix/ fix warnings, fix focus issue, removing extra code related to focus management. \n\n* Small fix/ settings_inpu_dialog warnings. \n\n* Fix slider focus for settings_inpu_dialog.dart SettingsSliderDialog. \n\n* Small fix/ add-profile slider focus. \n\n* Fix/ prevent scope switch while overlay is displayed. \n\n* Remove/ add_manual_profile_modal.dart. \n\n* Fix/ focus issue for adaptive-scaffold, add keyboard const, fix adaptive_root_scaffold warnings. \n\n* Small fix/ connection button focus color. \n\n* Small fix/ improve home_page logic and ui. \n\n* Fix/rewrite intro_page & fix rich text focus, remove _dynamicRootKey, add intro const. \n\n* Small fix/ hide adaptive scaffold from intro, fix warnings for routes.dart. \n\n* Fix/ merge add profile with manual modal(logic & ui), fix cancel for manual. \n\n* Small fix/ config_options_page(async await) \n\n* Small fix/ warning(use StringBuffer instead of String) \n\n* Small fix/ import warning. \n\n* Small fix/ log message. \n\n* Package update/ launch_at_startup. \n\n* Small fix/ fix waring for config_options_page. \n\n* Merge pull request #22 from veto9292/fix/reported-issues. \n  _Fix/reported issues_\n\n* Small fix/ update profile_parser_test. \n\n* Small fix/ free profile typo. \n\n* Merge pull request #21 from veto9292/fix/reported-issues. \n  _Fix/reported issues_\n\n* Small fix/ neededFeatures(warp to warp_over_proxies) \n\n* Fix/ free profile typo. \n\n* New/ overriding profile name and options locally and remotely(profile, fragment, name) \n\n* Update. \n\n* Update core. \n\n* Update flutter. \n\n* Update pipeline. \n\n* Change default connection test url to apple. \n\n* Merge branch 'new-design-v2' of https://github.com/hiddify/hiddify-next-ios into new-design-v2. \n\n* Merge pull request #20 from veto9292/fix/reported-issues. \n  _Fix/reported issues_\n\n* Small fix/ prefer_const_constructors. \n\n* Small fix/ prefer_final_locals. \n\n* Small fix/ remove commented imports. \n\n* Small fix/ remove unused_import. \n\n* Fix/ UI blocking during connection. \n\n* Feature/ support for enable-warp in profile headers. \n\n* Improve/ sync tray begavior in macOS with other Desktops. \n\n* Improve/ add support for custom scheme in flutter. \n\n* Setup/ add schemes for Windows. \n\n* Setup/ add schemes for Linux. \n\n* Setup/ add schemes for macOS. \n\n* Setup/ add schemes for iOS. \n\n* Setup/ add schemes for Android. \n\n* Feature/ ability to delete active profile. \n\n* Improve/ show sort profile dialog. \n\n* Small fix/ format source code, fix warning. \n\n* Small fix/ 'no active profile' dialog boxConstraints. \n\n* Moving interrupt handling in proxy reception to core. \n\n* Update to fultter 3.29.3. \n\n* Add profilename in start. \n\n* Merge branch 'new-design-v2' of https://github.com/hiddify/hiddify-next-ios into new-design-v2. \n\n* Merge pull request #19 from veto9292/fix/reported-issues. \n  _Fix/reported issues_\n\n* Small fix/ tray manager logic, bootstrap import. \n\n* Fix tray_manager, logic rewrite. \n\n* Fix proxy_overview_page performance issue, improve UI. \n\n* Hide back button for profiles_overview_page. \n\n* Improve ux and logic for add_profile_modal by showing region specific message (translation changed) \n\n* Custom scheme setup for registration in Windows OS (unpackaged app) \n\n* Setup app_links for flutter, merge app_links with go_router. \n\n* Setup app_links package for Linux. \n\n* Setup app_links package for macOS. \n\n* Setup app_links package for Windows OS. \n\n* Improve performance. \n\n* Add upload to app-draft. \n\n* Improve windows luncher. \n\n* Merge branch 'new-design-v2' of https://github.com/hiddify/hiddify-next-ios into new-design-v2. \n\n* Merge pull request #18 from veto9292/fix/reported-issues. \n  _Fix/reported issues_\n\n* Create custom_text_scroll, fix ButtonSegment over flow. \n\n* Fix loading height for add_profile_modal. \n\n* Justification is not possible, remove WrapAlignment.spaceBetween. \n\n* Remove percent_indicator_premium, fix profile_tile RemainingTrafficIndicator. \n\n* Fix per_app_proxy performance issue. \n\n* Remove protocol_handler from Windows and macOS. \n\n* Fix macos. \n\n* Merge branch 'new-design-v2' of https://github.com/hiddify/hiddify-next-ios into new-design-v2. \n\n* Merge pull request #17 from veto9292/fix/reported-issues2. \n  _Fix/reported issues2_\n\n* Fix deep link query-parameter. \n\n* Fix go router refreshListenable. \n\n* Handle deep link with go router. \n\n* Remove protocol_handler, deep_link_notifier. \n\n* Fix bottom sheets padding. \n\n* Fix per app proxy error. \n\n* Edit routes location. \n\n* Fix canChangeOption. \n\n* Fix ChoicePreferenceWidget enable (Enable WARP/Detour Mode) \n\n* Hide auto generated back button for settings page. \n\n* Return to home page from settings page when back button pressed. \n\n* Improve ux, preventing back when user intent to work with slider. \n\n* Preventing delete selected profile. \n\n* Update deoebdebcies. \n\n* Merge pull request #15 from veto9292/fix/reported-issues. \n  _fix reported issues and add en, fa translations_\n\n* Fix reported issues and add en, fa translations. \n\n* Improve android stability. \n\n* Upgrade flutter to 3.29.1. \n\n* Update ios macos. \n\n* Merge pull request #14 from veto9292/fix/proto-and-sentry. \n  _Fix/proto and sentry_\n\n* Remove protoc_builder. \n\n* Add .sentry-native to .gitignore. \n\n* Delete .sentry-native folder. \n\n* Fix route_rule.pb.dart import. \n\n* Merge pull request #13 from veto9292/feature/route-rule. \n  _Feature/route rule_\n\n* Route rule(not complete) \n\n* Add route rule regex validators. \n\n* Add riverpod_observer for better debugging. \n\n* Config-option file import/export. \n\n* Custom okText for confirmationDialog and fix content constraints. \n\n* Add package to pubspec.yaml(file_picker, installed_apps, recase) \n\n* Fix android. \n\n* Move proto to core. \n\n* Merge pull request #12 from veto9292/fix/add-profile. \n  _empty region in free config mean all, fix grid crossAxisCount for single item_\n\n* Empty region mean all, fix grid crossAxisCount for single item. \n\n* Merge pull request #11 from veto9292/update/add-profile. \n  _update/add_profile_modal_\n\n* Update/add_profile_modal add/free profiles to add_profile_modal remove/http package from pubspec.yaml. \n\n* Merge pull request #8 from veto9292/fix/makefile. \n  _fix: makefile path issue in Windows OS_\n\n* Merge pull request #10 from veto9292/feature/route-rule. \n  _add: proto packages & route_rule.proto file_\n\n* Add: proto packages & route_rule.proto file. \n\n* Fix windows compile. \n\n* Improve ios  and windows. \n\n* Disallow delete active profile. \n\n* Better connection management, add bounce and show connection error. \n\n* Make easier access for quick setuo. \n\n* Refactor config options. \n\n* Update pods. \n\n* Update sentry. \n\n* Update. \n\n* Update sqlite3 dependency. \n\n* Update flutter. \n\n* Handle profile size. \n\n* Support correctly ios. \n\n* Update android libs. \n\n* Update packages. \n\n* Show error incase of fail. \n\n* Upgrade flutter. \n\n* Some refactor. \n\n* Refactor router. \n\n* Refactor: routes. \n\n* Update. \n\n* Merge branch 'ios' into new-design-v2. \n\n* Update dialog to platform dialog. \n\n* Merge remote-tracking branch 'origin/main' into ios. \n\n* Update. \n\n* Update. \n\n* Merge branch 'fix-latest' into new-design. \n\n* Update packages and fix web issues. \n\n* V3. \n\n* New UI design. \n\n* Merge remote-tracking branch 'origin/main' into ios-pv. \n\n* Add make with love in intro. \n\n* Improve ios UI and integrate it with os. \n\n* Update. \n\n* Update ios. \n\n* Remove 'needed_features' from free_configs. \n\n* Update free_configs. \n\n* Update cron schedule and add operations limit. \n\n* Modify stale.yml for cron schedule and messages. \n  _Updated the stale issue workflow to change the cron schedule and modify the stale issue message and timing._\n\n* Update warp configuration with new server entries. \n\n* Update profile title in warp configuration. \n\n* Add new warp configurations and psiphon links. \n\n* Update title in free_configs for Warp profile. \n\n* Remove unused configurations for Insta-Youtube and Ainita. \n  _Removed several configurations related to Insta-Youtube and Ainita.net, including their titles, sublinks, tags, and consent messages._\n\n* Change region from '-' to 'k' in free_configs. \n  _Updated region values from '-' to 'k' for two configurations._\n\n* Add Mahsa profile configuration file. \n\n* Add Mahsa configuration profile to free_configs. \n\n* Update free_configs. \n\n* Update warp configuration with new detour format. \n\n* Update free_configs. \n\n* Update free_configs. \n\n* Create ainita. \n\n* Update free_configs. \n\n* Chore: update translations with Fink 🐦 \n\n* Update super_fragment. \n\n* Update super_fragment. \n\n* Update super_fragment. \n\n* Update super_fragment. \n\n* Rename super_fragment.json to super_fragment. \n\n* Update super_fragment.json. \n\n* Create super_fragment.json. \n\n* Update free_configs. \n\n* Update free_configs. \n\n* Create free_configs. \n\n* Update fragment. \n\n* Update fragment. \n\n* Update fragment. \n\n* Create fragment. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_br.md. \n\n* Update README_ja.md. \n\n* Update README_br.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_ru.md. \n\n* Update README_ja.md. \n\n* Update README_fa.md. \n\n* Update README_cn.md. \n\n* Update README_br.md. \n\n* Update README.md. \n\n* Merge pull request #1475 from simonkimi/main. \n  _Profile Tile InkWell Overflow Fix_\n\n* Fix profile_tile clipBehavior. \n\n* Update README.md. \n\n* Merge pull request #1464 from kekomenos/patch-1. \n  _Update README.md_\n\n* Update README.md. \n  _<!-- Copy-paste in your Readme.md file -->\r\n\r\n<a href=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history?repo_id=643504282\" target=\"_blank\" style=\"display: block\" align=\"center\">\r\n  <picture>\r\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=dark\" width=\"721\" height=\"auto\">\r\n    <img alt=\"Star History of hiddify/hiddify-app\" src=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=light\" width=\"721\" height=\"auto\">\r\n  </picture>\r\n</a>\r\n\r\n<!-- Made with [OSS Insight](https://ossinsight.io/) -->_\n\n* Update README.md. \n\n* Create README.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_ja.md. \n\n* Update README_br.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README_br.md. \n\n* Update README_ja.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Merge pull request #1438 from proninyaroslav/linux-fix-silent. \n  _[Linux] Fix minimize to tray (silent start) option_\n\n* [Linux] Fix minimize to tray if the option is enabled. \n\n* Update LICENSE.md. \n\n* Update CONTRIBUTING.md. \n\n* Update README.md. \n\n* Merge pull request #1403 from ldm0206/main. \n  _Update translations zh-CN_\n\n* Chore: update translations with Fink 🐦 \n\n\n\n## v2.5.7 (2024-10-03)\n\n#### Other\n\n* Merge pull request #1382 from TheLastFlame/main. \n  _Remembering window closing action_\n\n* Feat: add action options for closing the application. \n\n* Chore: update .gitignore to exclude /data directory. \n\n* Refactor: replace HookConsumerWidget with ConsumerWidget and add ThemeModePrefTile. \n\n\n\n## v2.5.6 (2024-10-02)\n\n#### Fix\n\n* Version bug. \n\n* Version bug. \n\n\n\n## v2.5.5 (2024-09-29)\n\n#### Other\n\n* Merge pull request #1368 from tarzst/main. \n  _Update RU translations_\n\n* Chore: update translations with Fink 🐦 \n\n\n\n## v2.5.2 (2024-09-29)\n\n#### Fix\n\n* Typo. \n\n\n\n## v2.5.1 (2024-09-29)\n\n#### Fix\n\n* Exception. \n\n* Version. \n\n\n\n## v2.5.0 (2024-09-28)\n\n#### Other\n\n* Merge pull request #1335 from laperuz92/patch-1. \n  _Update russian translations_\n\n* Update russian translations. \n\n* Merge pull request #1328 from yxiZo/main. \n  _Update translations_\n\n* Chore: update translations with Fink 🐦 \n\n* Merge pull request #1322 from andythesilly/main. \n  _set edgeToEdge ui mode_\n\n* Chore: update translations with Fink 🐦 \n\n* Set edgeToEdge ui mode. \n\n\n\n## v2.3.1 (2024-09-07)\n\n#### Fix\n\n* Android. \n\n#### Other\n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Change name to hiddifypackettunnel. \n\n* Fix android build issue. \n\n\n\n## v2.3.0 (2024-09-02)\n\n#### New\n\n* Add brazil region. \n\n#### Fix\n\n* Black screenn when press back button. \n\n#### Other\n\n* Hide back icon when no back. \n\n* Merge pull request #1277 from sillydillydiddy/main. \n  _Update translations_\n\n* Chore: update translations with Fink 🐦 \n\n* Merge pull request #1282 from vedantmgoyal9/patch-1. \n  _Update winget-releaser to latest_\n\n* Update winget.yml. \n\n* Update winget.yml. \n\n* Update winget-releaser to latest. \n\n* Merge pull request #1278 from tensionc/main. \n  _fix: Black screenn when press back button_\n\n* Merge remote-tracking branch 'origin/main' \n\n* Update warp. \n\n* Update warp. \n\n* Revert: Keep button, add judgment. \n\n\n\n## v2.2.0 (2024-08-21)\n\n#### New\n\n* Add several values for dns and url test in auto complete mode. \n\n* Add use xray core option. \n\n#### Changes\n\n* Default tun mode to gvisor. \n\n#### Fix\n\n* Bug. \n\n* Some hard coded items. \n\n* Apple bug. \n\n* Bug of back button in rtl flutter 3.24. \n\n* Naming of links containing &&detour. \n\n#### Other\n\n* Better auto complete. \n\n* Remove hindi. \n\n* Update flutter to 3.24. \n\n* Merge pull request #1217 from lexxfin/main. \n  _chore: update translations with Fink 🐦_\n\n* Chore: update translations with Fink 🐦 \n\n* Merge pull request #1210 from bLueriVerLHR/main. \n  _Fix typo in stats_repository.dart_\n\n* Fix typo in stats_repository.dart. \n\n* Chore: update translations with Fink 🐦 \n\n* Include app configs before validaing proxies. \n\n* Chore: update translations with Fink 🐦 \n\n* Change default warp mode to m4. \n\n\n\n## v2.1.5 (2024-08-05)\n\n#### Fix\n\n* Vpn service issue. \n\n#### Other\n\n* Revert android changes. \n\n* Fix warp generation. \n\n* Try fix vpn. \n\n* Check macos. \n\n* Disable mac. \n\n* Revert changes to android vpn service. \n\n* Better tryicons. \n\n\n\n## v2.1.4 (2024-08-05)\n\n#### New\n\n* Add exit dialog when press close button. \n\n* Colorized tray icon. \n\n#### Fix\n\n* Some bugs. \n\n* Bugs in tray icon. \n\n* Fr trnalsation. \n\n* Translate bug. \n\n* Single instance flutter in linux? \n\n#### Other\n\n* Less retry for ipinfo. \n\n* Add french lang. \n\n* Test icon linux? \n\n* Connection button by proxy status indicator, change connected to connecting when timeout. \n\n* Formated export in json editor. \n\n* Merge pull request #1174 from Hannisiddiqui/main. \n  _Wanted to add hindi language for indian users_\n\n* Inlang/manage: add languageTag hi. \n\n* Inlang/manage: install module. \n\n* Chore: update translations with Fink 🐦 \n\n* Chore: update translations with Fink 🐦 \n\n* Chore: update translations with Fink 🐦 \n\n* Chore: update translations with Fink 🐦 \n\n* Chore: update translations with Fink 🐦 \n\n* Update warp. \n\n* Update release_message.md. \n\n\n\n## v2.1.1 (2024-08-02)\n\n#### New\n\n* Add turkey region. \n\n#### Other\n\n* Add change log. \n\n\n\n## v2.1.0 (2024-08-02)\n\n#### New\n\n* Add invalid config label. \n\n#### Fix\n\n* Error migrating from v3 to v4 database. \n\n* Url test issues, avoid multiple test, and change outbound on test. \n\n* Loop in android. \n\n#### Other\n\n* Merge pull request #1162 from soyangelromero/main. \n  _Update translations EN - ES_\n\n* Chore: update translations with Fink 🐦 \n\n* Merge pull request #1154 from MR-TZ-dev/main. \n  _fix: error migrating from v3 to v4 database._\n\n* Better get requests. \n\n* Fix; font. \n\n\n\n## v2.0.4 (2024-07-31)\n\n#### New\n\n* Add rich config editor. \n\n\n\n## v2.0.3 (2024-07-30)\n\n#### Fix\n\n* Bug. \n\n\n\n## v2.0.2 (2024-07-30)\n\n#### Other\n\n* Better editor. \n\n\n\n## v2.0.1 (2024-07-30)\n\n#### Fix\n\n* Ios build issue. \n\n* Ios bug. \n\n* Some bugs in configs and fix core bugs. \n\n* Editor text mode bug. \n\n#### Other\n\n* Update. \n\n* Better json editor. \n\n* Test. \n\n* Use latest macos for build ios. \n\n* Test ios. \n\n\n\n## v2.0.0 (2024-07-30)\n\n#### New\n\n* Add json editor and editing configs <3. \n\n* Add custom url-test for each repository. \n\n#### Fix\n\n* Link validator. \n\n* Provis? \n\n* Ios. \n\n#### Other\n\n* Update warp. \n\n* Fix? \n\n* Ios? \n\n* Fix ios? \n\n* Fix bug. \n\n\n\n## v1.9.1 (2024-07-28)\n\n#### New\n\n* Add auto build for ios. \n\n* Add xray type. \n\n#### Fix\n\n* Add warp issue. \n\n#### Other\n\n* Revert to sdk 34. \n\n* Enable resolve-destination and ipv6 by default. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Merge pull request #1108 from SonzaiEkkusu/main. \n  _Update Translations for Region Indonesia (id)_\n\n* Update Translations for Region Indonesia (id) \n\n* Reset direct dns when region  change. \n\n* Update sdk to 35. \n\n* Better xray support. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Merge pull request #1106 from amirsaam/main. \n  _General iOS Maintain_\n\n* General iOS Maintain. \n\n\n\n## v1.9.0 (2024-07-25)\n\n#### New\n\n* Add10000 to all ports for prevenging permission error. add warp from github repository except for china. \n\n#### Fix\n\n* Fixed problem not launching on Ubuntu 24.04 LTS. \n\n#### Other\n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Merge pull request #1084 from MR-TZ-dev/fix/linuxLaunchFix. \n  _fix: fixed problem not launching on Ubuntu 24.04 LTS._\n\n* Merge pull request #1092 from Metozak/main. \n  _Update translations_\n\n* Chore: update translations with Fink 🐦 \n\n* Merge pull request #1097 from SonzaiEkkusu/main. \n  _Add Indonesia region_\n\n* Add Indonesia region. \n\n* Add core to 1.9.0. \n\n* Upgrade flutter. \n\n* Merge pull request #1073 from keyang556/main. \n  _Update translations_\n\n* Chore: update translations with Fink 🐦 \n\n* Update warp. \n\n* Update warp2. \n\n* Update warp2. \n\n\n\n## v1.7.0 (2024-07-17)\n\n#### New\n\n* Add more warp modes, handle both ipv4 and ipv6 in wireguard, add customizable size and more. \n\n#### Other\n\n* Update warp2. \n\n* Create warp2. \n\n* Update warp. \n\n\n\n## v1.6.3 (2024-07-14)\n\n#### Other\n\n* Make pre-release by default. \n\n\n\n## v1.6.2 (2024-07-14)\n\n#### Fix\n\n* Qrcode issue and update qrcode lib. \n\n* Scanner. \n\n#### Other\n\n* Renew warp configs on adding. \n\n\n\n## v1.6.1 (2024-07-14)\n\n#### New\n\n* Add knocker parameters. \n\n#### Fix\n\n* Release issue. \n\n* Qrcode issue. \n\n#### Other\n\n* Android. \n\n* Upgrade flutter. \n\n* Update flutter and make connection more smooth. \n\n* Show info dialog when reconnecting. \n\n* Merge pull request #1050 from itispey/dev-test. \n  _Reconnect automatically after changing service-mode_\n\n* Reconnect automatically after changing service-mode. \n\n* Merge pull request #1053 from maxyxyd/main. \n  _Update translations_\n\n* Chore: update translations with Fink 🐦 \n\n* Chore: update translations with Fink 🐦 \n\n* Chore: update translations with Fink 🐦 \n\n* Chore: update translations with Fink 🐦 \n\n* Merge pull request #1043 from nidghogg/main. \n  _Fixed camera permission handling for QR_\n\n* Merge branch 'main' of https://github.com/nidghogg/hiddify-next. \n\n* Fixed Camera permission handling for QR. \n\n\n\n## v1.5.0 (2024-07-09)\n\n#### Fix\n\n* Test bug for geoassets. \n\n* Remove geoassets. \n\n#### Other\n\n* Fix intro page buug. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Merge pull request #1004 from Kianmehrgit/main. \n  _Update translations_\n\n* Chore: update translations with Fink 🐦 \n\n* Merge pull request #993 from fodhelper/fix-urltest-fails. \n  _Fix URLTest Fails_\n\n* Update config_option_repository.dart. \n\n* Merge pull request #966 from SoranTabesh/main. \n  _Update translations_\n\n* Chore: update translations with Fink 🐦 \n\n* Merge pull request #965 from SoranTabesh/patch-1. \n  _Update locale_extensions.dart_\n\n* Update locale_extensions.dart. \n\n* Merge pull request #988 from Amirali-Amirifar/fix-changelog-update-years. \n  _Fix CHANGELOG year_\n\n* Fix CHANGELOG year. \n  _see diff._\n\n* Merge pull request #934 from amirsaam/main. \n  _General iOS Maintaining_\n\n* General iOS Maintaining. \n\n* Refactor. \n\n* Add basic routing options, auto update routing assets,use ruleset, remove geo assets. \n\n\n\n## v1.4.0 (2024-06-02)\n\n#### Fix\n\n* Naming bug. \n\n* Bug. \n\n* Bug. \n\n* Ios. \n\n* Lang. \n\n* Bug. \n\n* Make dark tray icon windows-only. \n\n#### Other\n\n* Merge pull request #817 from felixhaeberle/main. \n  _Update translations_\n\n* Merge branch 'main' into main. \n\n* Chore: update translations with Fink 🐦 \n\n* Chore: update translations with Fink 🐦 \n\n* Merge pull request #811 from amirsaam/main. \n  _New Bundle + Pods + PrivacyAPIs_\n\n* Privacy Targets. \n\n* Privacy Declaration. \n\n* New Bundle + Pods. \n\n* Merge branch 'android-fix-action-bug' \n\n* Downgrade flutter. \n\n* Master. \n\n* Downgrade to 3.22.0. \n\n* Upgrade flutter. \n\n* Update to flutter 3.21. \n\n* Update. \n\n* Downgrade flutter. \n\n* Temporary disbale apk build. \n\n* Update. \n\n* Update. \n\n* Test. \n\n* Update. \n\n* Update. \n\n* Upgrade gradle version. \n\n* Tmp test. \n\n* Add more log. \n\n* Update flutter action. \n\n* Add debug and ios. \n\n* Fix lang update. \n\n* Merge pull request #778 from Pikman/main. \n  _Update translations_\n\n* Merge branch 'main' into main. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Merge pull request #894 from xmha97/main. \n  _Capitalize the installation folder_\n\n* Update make_config.yaml. \n\n* Merge pull request #902 from MrIbrahem/main. \n  _Update ar translations_\n\n* Chore: update translations with Fink 🐦 \n\n* Merge pull request #4 from MrIbrahem/patch-1. \n  _Patch 1_\n\n* Update strings_ar.i18n.json. \n\n* Update strings_ar.i18n.json. \n\n* Update strings_ar.i18n.json. \n\n* Update strings_ar.i18n.json. \n\n* Update make_config.yaml. \n\n* Update settings.json. \n\n* Update locale_extensions.dart. \n\n* Merge pull request #3 from MrIbrahem/patch-1. \n  _Update strings_ar.i18n.json_\n\n* Update strings_ar.i18n.json. \n\n* Update strings_ar.i18n.json. \n\n* Merge pull request #2 from MrIbrahem/patch-1. \n  _Create strings_ar.i18n.json_\n\n* Create strings_ar.i18n.json. \n\n* Merge pull request #814 from keyang556/main. \n  _Update Traditional Chinese translations_\n\n* Chore: update translations with Fink 🐦 \n\n* Chore: update translations with Fink 🐦 \n\n* Chore: update translations with Fink 🐦 \n\n* Add warp config, update to flutter 1.22. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Merge pull request #770 from alkstsgv/main. \n  _Update translations_\n\n* Fink 🐦: update translations. \n\n* Test. \n\n* Merge pull request #751 from sky96111/main. \n  _fix: make auto dark tray icon windows-only_\n\n* Merge pull request #737 from SoranTabesh/main. \n  _Update translations_\n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Rename strings_ckb-KU.i18n.json to strings_ckb-KUR.i18n.json. \n\n* Update settings.json. \n\n* Fink 🐦: update translations. \n\n* Update README_br.md. \n\n* Update README_ja.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update core. \n\n* Merge pull request #726 from HSSkyBoy/main. \n  _inlang: update zh-TW transition_\n\n* Update zh-TW transition. \n\n* Merge pull request #705 from iamgiko/main. \n  _Update translations_\n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n* Update LICENSE.md. \n\n* Update LICENSE.md. \n\n* Update README_ru.md. \n\n* Update README_ja.md. \n\n* Update README_cn.md. \n\n* Update README_ja.md. \n\n* Update README_br.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Merge pull request #698 from betaxab/p1. \n  _inlang: update translations_\n\n* Inlang: update translations. \n\n\n\n## v1.1.1 (2024-03-20)\n\n#### New\n\n* Add tproxy. \n\n#### Fix\n\n* Gvisor. \n\n* Issue. \n\n#### Other\n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Merge pull request #696 from HSSkyBoy/main. \n  _Update translations (zh_TW and zh_CN)_\n\n* 更新 strings_zh-TW.i18n.json. \n\n* 更新 strings_zh-TW.i18n.json. \n\n* Update strings_zh-TW.i18n.json. \n\n* 更新 strings_zh-TW.i18n.json. \n\n* Change APP name. \n\n* 更新 strings_zh-TW.i18n.json. \n\n* 更新 strings_zh-CN.i18n.json. \n\n* Bump version. \n\n* Merge pull request #692 from sky96111/main. \n  _Update translations_\n\n* Fink 🐦: update translations. \n\n* Merge pull request #686 from sky96111/main. \n  _feat: Use dark tray icon in light theme_\n\n* Feat: dark tray icon in light theme. \n\n* Merge pull request #690 from imshahab/m3-dynamic-theme. \n  _Implement Material 3 dynamic theming_\n\n* Implement Material 3 dynamic theming. \n\n* Merge pull request #685 from Nyar233/main. \n  _Update translations_\n\n* Fink 🐦: update translations. \n\n* Merge pull request #682 from alirezafarvardin/main. \n  _Update translation (Persian)_\n\n* Merge branch 'main' into main. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Update bug_report.yaml. \n\n* Fink 🐦: update translations. \n\n* Fink 🐦: update translations. \n\n\n\n## v1.0.0 (2024-03-18)\n\n#### New\n\n* Add review. \n\n#### Fix\n\n* Isssue with singbox 1.8.9. \n\n* Ios. \n\n* Implementation. \n\n* Test, update to singbox 1.8.9. \n\n* Bug in warp config. \n\n#### Other\n\n* Update release_message.md. \n\n* Update README.md. \n\n* Update README_br.md. \n\n* Update README_ja.md. \n\n* Update README_cn.md. \n\n* Update README_ru.md. \n\n* Update README_ru.md. \n\n* Update README_fa.md. \n\n* Update README_ru.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_ja.md. \n\n* Update README_br.md. \n\n* Update README.md. \n\n* Update release_message.md. \n\n* Update README.md. \n\n* Fix postServiceClose implementation. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Fink 🐦: update translations. \n\n* Remove mux. \n\n* Merge branch 'pr/alikhabazian/668-1' \n\n* Resolve qr code permssion issue. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Merge pull request #668 from alikhabazian/newyear. \n  _add image field to ConnectionButton_\n\n* Add useImage feild for change image in every newyear and increase quality. \n\n* Add image field to ConnectionButton. \n\n* Update. \n\n* Merge pull request #653 from alirezafarvardin/main. \n  _Update translations_\n\n* Inlang/manage: add languageTag zh-TW. \n\n* Inlang/manage: add languageTag zh-CN. \n\n* Inlang/manage: add languageTag tr. \n\n* Inlang/manage: add languageTag ru. \n\n* Inlang/manage: add languageTag pt-BR. \n\n* Inlang/manage: add languageTag id. \n\n* Inlang/manage: add languageTag es. \n\n* Inlang/manage: remove languageTag es. \n\n* Inlang/manage: add languageTag es. \n\n* Inlang/manage: remove languageTag zh-CN. \n\n* Inlang/manage: remove languageTag id. \n\n* Inlang/manage: remove languageTag ru. \n\n* Inlang/manage: remove languageTag tr. \n\n* Inlang/manage: remove languageTag es. \n\n* Inlang/manage: remove languageTag zh-TW. \n\n* Inlang/manage: remove languageTag pt-BR. \n\n* Merge branch 'hiddify:main' into main. \n\n* Fink 🐦: update translations. \n\n* Test flight only release. \n\n* Add core grpc server. \n\n\n\n## v0.17.12 (2024-03-14)\n\n#### New\n\n* Refactor testflight. \n\n* Add installation dependencies for apple. \n\n* Add ios build process. \n\n* Add Indonesian language. \n\n* Add hiddifycli and resolve all false positve from anti virus, auto exit during installation. \n\n* Add support for flag emoji in proxy names. \n\n* Add version draft. \n\n* Auto replace signed exec. \n\n* Update to singboc 1.8.7. \n\n* Enable tunnel service again, add signing, msix, more log less info. \n\n* Add ipwho.is. \n\n* Use timezone for location detector. \n\n* Add warp fake packet delay, add warp detour, add new ipinfo api. \n\n#### Fix\n\n* Apple release. \n\n* Bug. \n\n* No commit message. \n\n* Release to ios. \n\n* Ios publishing. \n\n* Var. \n\n* Var. \n\n* Vaiable issue. \n\n* Potential fix to issue in some windows? \n\n* Msix package. \n\n* Signing. \n\n* Version. \n\n* Pub get issue? \n\n* Build. \n\n* Flag. \n\n* Ip flag. \n\n* Bug in versioned draft. \n\n* Invalid version string for draft. \n\n* Action bugs. \n\n* Signing. \n\n* Signing. \n\n* Cert? \n\n* Generate Warp Config on iOS. \n  _+ pod install new packages_\n\n* Msix issue. \n\n* Appimage fixed. issue: #513. \n\n* Name. \n\n* Intro page bug and fakepacket delay bug. \n\n* Exception reporting on failing in getting ip. \n\n* Exception when there is no active profile. \n\n* Ip info. \n\n* Build bug. \n\n* Translation bug, disable signing for pull req. \n\n* Bug in change interface listener. \n\n* Update download paths in release page. \n\n* Logo, add name for hiddify warp sub. \n\n#### Other\n\n* Update. \n\n* Update. \n\n* Update. \n\n* Update. \n\n* Update. \n\n* Disable: permission handler for windows. \n\n* Disable redundent action run for release. \n\n* Merge pull request #647 from hiddify/ios. \n  _Ios_\n\n* Upload versioned. \n\n* Update. \n\n* Update. \n\n* Update ios release. \n\n* Upload to appstore in macos. \n\n* Test testflight upload. \n\n* Fix name issue. \n\n* Update. \n\n* Update. \n\n* Update. \n\n* Add provisioning profiles. \n\n* Add SingBoxPacketTunnel. \n\n* Update. \n\n* Update. \n\n* Add prereq of ios. \n\n* Allow ci build from all branches. \n\n* Revert changes for test. \n\n* Test disabling system tray. \n\n* A test for possible bug in some windows. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Update signing. \n\n* Downgrade flutter action. \n\n* Merge pull request #621 from hei-hilman/main. \n  _add new translation (Indonesian)_\n\n* Add indonesian translation. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Fix qr code scanner. \n\n* Change translation keys. \n\n* Change experimental feature notice. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Change sidebar stats. \n\n* Add emoji font for flags. \n\n* Use software rendering for windows. may resolve white screen? \n\n* Update README_br.md. \n\n* Update README_ja.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Refactor config options. \n\n* Merge branch 'be1c1bb580ec039044e8057ae1469153008cdb4d' \n\n* Add reconnect and animations to connection button. \n\n* Add quick settings. \n\n* Update release_message.md. \n\n* Bump Flutter (v3.19) and dependencies. \n\n* Remove redundant logs. \n\n* Change db initialization. \n\n* Remove draft version. \n\n* Make it universal for all os. \n\n* Add versioned draft. \n\n* Simple debug to bug of some windows. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Add Config options import. \n\n* Disable signing. \n\n* Add hide icon from dock on mac. \n\n* Add reconnect alert for config options. \n\n* Refactor preferences. \n\n* Merge pull request #585 from amirsaam/main. \n\n* Update msix. \n\n* Merge pull request #577 from Aryangh1379/Hiddify-develop. \n\n* Merge pull request #572 from Aryangh1379/Hiddify-develop. \n  _Hiddify develop_\n\n* Forgot to remove -x from !#/bin/bash :) \n\n* Add AppRun parameters - provided a help menu. \n\n* Temporary disable windows service. \n\n* Update README.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_cn.md. \n\n* Update README_cn.md. \n\n* Update README_ru.md. \n\n* Update README_ru.md. \n\n* Update README_ja.md. \n\n* Update README_fa.md. \n\n* Update README_br.md. \n\n* Merge pull request #532 from mascenaa/main. \n  _Add README in Portuguese_\n\n* Adding a README in Portuguese. \n\n* Merge pull request #556 from Aryangh1379/Hiddify-develop. \n  _AppRun file error fixed. AppImage now is usable_\n\n* AppRun file error fixed. AppImage now is usable. \n\n* Merge pull request #549 from pierrot-p/main. \n  _[PT-BR]  inlang: Added missing translations_\n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Merge pull request #546 from nya-main/main. \n  _update translations(CN)_\n\n* Manually repair an entry. \n\n* Inlang: update translations. \n\n* Merge pull request #547 from amirsaam/main. \n  _macOS AppIcon_\n\n* MacOS AppIcon. \n\n* Add timezone based region detection. \n\n* Url test is only valid for group not a single proxy. \n\n* Potentioal fix for crash in some windows. \n\n* Bump libcore. \n\n* Excluding aab from building draft. \n\n* Remove aab draft build. \n\n* Change warp options. \n\n* Fix Portuguese locale. \n\n* Add build test. \n\n* Update dependencies. \n\n* Change ip error. \n\n* Remove extra warp configs. \n\n* Update README_ru.md. \n\n* Merge pull request #509 from nevazno00/patch-1. \n  _Update README_ru.md_\n\n* Update README_ru.md. \n\n* Merge pull request #527 from mascenaa/main. \n  _Add a PT-BR Translate file._\n\n* Add a PT-BR Translate file. \n\n* Merge pull request #508 from kouhe3/zh-cn-i18n-patch-2. \n  _strings_zh-CN.i18n.json_\n\n* Merge branch 'main' into zh-cn-i18n-patch-2. \n\n* Merge pull request #523 from nya-main/main. \n  _Update translations_\n\n* Merge branch 'main' into main. \n\n* Merge pull request #528 from KintaMiao/main. \n  _Update translations_\n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Fix build. \n\n* Add more haptic feedback. \n\n* Zh-cn translate. \n\n* Detailed subscription info. \n\n* Add detailed subscription info. \n\n* Fix test. \n\n* Add ci test. \n\n* Add warp config generator. \n\n* Update changelog. \n\n* Change ip refresh. \n\n* Add auto ip check option. \n\n* Change ip error refresh button. \n\n* Change mapping. \n\n* Fix issue in installing packages in ubuntu. \n\n* Fix connection on desktop. \n\n* Change interval mapping. \n\n* Fix chinese locale. \n\n* Add haptic feedback. \n\n* Format zh-CN.i18n.json And remove duplicate. \n\n* Merge pull request #410 from junlin03/main. \n  _更新繁體中文翻譯_\n\n* Merge branch 'main' into main. \n\n* Merge pull request #482 from guoard/fix/downlaod_path. \n  _fix: update download paths in release page_\n\n* Merge pull request #481 from amirsaam/main. \n  _Bugs in config_option_entity.dart_\n\n* Update config_option_entity.dart. \n\n* Bugs in config_option_entity.dart. \n\n* Change mapping and bug fixes. \n\n* Change icons. \n\n* Improve ping indicator. \n\n* Change service mode choices. \n\n* Fix ip widget directionality. \n\n* Merge branch 'main' into main. \n\n* Inlang: update translations. \n\n\n\n## v0.15.8 (2024-02-14)\n\n#### New\n\n* Update icon. \n\n* Add seperated VPN service mode. \n\n* Add some example of new warp configs. \n\n* Update active profile and its ping, \n\n* Change app icon to stable. \n\n* Add unavailble mark, fix: windows release bug. \n\n#### Changes\n\n* Change name to Hiddify. \n\n#### Fix\n\n* Appimage tunnel service bug. \n\n#### Other\n\n* Change ip obscure. \n\n* Improve accessibility. \n\n* Change service error handling. \n\n* Fix connection info. \n\n* Fix widget build conflict. \n\n* Revert build image for appimage to 22.04. \n\n* Update README_cn.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README_ja.md. \n\n* Update README_fa.md. \n\n* Update README_ru.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_cn.md. \n\n* Update README_ja.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Merge pull request #454 from amirsaam/main. \n  _Update iOS Icons_\n\n* AppIcon Update. \n\n* Update iOS Icons. \n\n* Add proxy http adapter. \n\n* Fix android service mode. \n\n* Merge pull request #453 from amirsaam/main. \n  _Update Makefile_\n\n* Update Makefile. \n\n* Change routing setup. \n\n* Fix connection info ui. \n\n* Make ip private for both footer and sidebar. \n\n* Make ip anonymous. \n\n* Add syncthing ignore files. \n\n* Add desktop active proxy info. \n\n* Add active proxy delay indicator. \n\n* Fix commands. \n\n* Change translation fallback strategy. \n\n* Update CONTRIBUTING.md. \n\n* Merge pull request #439 from amirsaam/main. \n  _Fix iOS Logger_\n\n* Fix iOS Logger. \n\n\n\n## v0.15.6 (2024-02-09)\n\n#### New\n\n* Add macos pkg file and remove zip wrapper. \n\n* Add custom AppRun: need forked distributor. \n\n* Add intro based on user lang and region. \n\n* Hide hidden nodes. \n\n* Move running admin service to core. \n\n* Display go errors. \n\n* Add tunnel service for windows and linux. \n\n* Show groups always on top. \n\n* Change update time when selected. \n\n* Make activated profile always in top. \n\n* Add postfix to name if it is not unique. \n\n* Add link parser and allow custom configs to be imported. \n\n#### Changes\n\n* Use our flutter distrobutor version and downgrade windows version (possible fix of build error) \n\n#### Fix\n\n* Unix copy bug. \n\n* Build linux. \n\n* Dynamic varible in github action. \n\n* Windows? \n\n* Windows build? \n\n* Typo. \n\n* Windows build. \n\n* Appimage build and add make req for linux. \n\n* Service location bug in linux. \n\n* Update of protocol handler. \n\n* Bug in logging go erros. \n\n* Check core before release. \n\n#### Other\n\n* Refactor  build. \n\n* Add debug build for windows. \n\n* Rerun windows without cache. \n\n* Add ios connection info. \n\n* Fix ui inconsistency. \n\n* Fix local build commands. \n\n* Fix android bugs. \n\n* Add connection info footer. \n\n* Add ip info fetcher. \n\n* Merge pull request #416 from EbrahimTahernejad/patch-1. \n  _Make logger global_\n\n* Use shared instance of logs to log. \n\n* Added shared instance for LogsEventHandler. \n\n* Merge pull request #414 from amirsaam/main. \n  _Log for iOS by @ Akuma_\n\n* Log for iOS by @ Akuma. \n\n* Add ios command client. \n\n* Change make flags. \n\n* Change the name of tunnel service to HiddifyService. \n\n* Make makefile cross platform. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Add cloudflare warp options. \n\n* Temporary disable app image build. \n\n* Change again to ubuntu 22.04. \n\n* Update ci.yml. \n\n* Disable tunnel service for mac. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Remove unnecessary dependencies. \n\n* Fix mobile routing behavior. \n\n* Bump java version. \n\n* Update dependencies. \n\n* Fix intro page margin. \n\n* Send panic to sentry. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Merge pull request #371 from eltociear/add_ja-readme. \n  _Add Japanese README_\n\n* Add Japanese README. \n\n* Merge pull request #389 from leic4u/patch-1. \n  _Update README_cn.md_\n\n* Update README_cn.md. \n\n* Update README.md. \n\n* Add mux to experiments && update translations. \n\n\n\n## v0.15.4 (2024-01-26)\n\n#### Fix\n\n* Fragment bug. \n\n\n\n## v0.15.3 (2024-01-26)\n\n#### New\n\n* Add warp option (experimental) \n\n#### Fix\n\n* Typo. \n\n#### Other\n\n* Bump to singbox 1.8.4, and fix bugs. \n\n* Refactor makefile. \n\n* Update Hiddify Packages. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update to core 0.12.1, singbox 1.8.2. \n\n* Update build.yml. \n\n* Make 1.1.1.1 as default dns server. \n\n* Speed up ping. \n\n* Update libcore. \n\n\n\n## v0.14.20 (2024-01-21)\n\n#### Other\n\n* Update feature_request.yaml. \n\n* Update bug_report.yaml. \n\n\n\n## v0.14.11 (2024-01-20)\n\n#### New\n\n* Add deb and rpm build. \n\n#### Fix\n\n* Versioning issue in ios singbox platform extension. \n\n* Release bug. \n\n* Release bug. \n\n* Build linux. \n\n* Stats bug in iOS. \n\n* Some bugs in ios. \n\n#### Other\n\n* Merge pull request #351 from amirsaam/main. \n  _use universal bundleid from base.xconfig_\n\n* Use universal bundleid from base.xconfig. \n\n* Merge pull request #350 from amirsaam/main. \n  _ios log handler base functionality_\n\n* Log handler base functionality. \n  _+ fix makefile ios-temp-prepare upgrading pub\n+ remove tvOS from libcore local spm\n+_\n\n* Add mux options. \n\n* Add mux. \n\n* Update release_message.md. \n\n* Update build.yml. \n\n* Update changelog. \n\n* Update readme. \n\n* Fix ios stats. \n\n* Add reset tunnel option on ios. \n\n* Update build.yml. \n\n* Fix release. \n\n* Fix release. \n\n* FIX: RELEASE BUG. \n\n* Fix release bug in macos. \n\n* Update build.yml. \n\n* Update build.yml. \n\n* Update build.yml. \n\n* Update dependencies. \n\n* Fix not releasing linux packages. \n\n* Merge pull request #347 from amirsaam/main. \n  _fix connection bug after bundle update_\n\n* Fix connection bug after bundle update. \n\n* Merge pull request #345 from amirsaam/main. \n  _update to latest itunes connect_\n\n* Update to latest itunes connect. \n\n* Revert changes for swift package. \n\n* Merge pull request #344 from amirsaam/main. \n  _switch to local spm to load libcore_\n\n* Merge branch 'main' of https://github.com/amirsaam/hiddify-next. \n\n* Merge branch 'hiddify:main' into main. \n\n* Remove tvOS in singbox target. \n\n* Remove tvOS, previously added apple vision for ipad. \n\n* Handle xcode crash. \n\n* Switch to local spm. \n\n* Fix make ios. \n\n* Bumpcore version to v0.11. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Merge pull request #343 from amirsaam/main. \n  _url scheme +  target dependency + general update_\n\n* Merge branch 'hiddify:main' into main. \n\n* Add url scheme. \n\n* Update Package.resolved. \n\n* Target dependancy + pod update, package resolve. \n\n* Remove hiddify://import/ from export option. \n\n* Merge pull request #342 from amirsaam/main. \n  _getting libcore from spm, adding landscape mode_\n\n* Merge branch 'main' of https://github.com/amirsaam/hiddify-next. \n\n* Delete pubspec.lock. \n\n* Revert some changers. \n  _This reverts some of commit dde7c2419a12e0f36976f4c0ff8e66d882ec62ac._\n\n* Update pod, getting libcore from spm, adding landscape mode. \n\n* Change profile options modal. \n\n* Fix infinite sub expire date (#334) \n  _* Fix infinite sub expire date\r\n\r\n* fix expire\r\n\r\n* fix build\r\n\r\n* refactor\r\n\r\n* make it better readable\r\n\r\n* Fix infinite sub\r\n\r\n* Add test for infinite sub\r\n\r\n---------_\n\n* Fix fragment bugs. \n\n* Merge pull request #340 from amirsaam/main. \n  _fix ui not showing connected after relaunch_\n\n* Fix ui not showing connected after relaunch. \n\n* Merge pull request #338 from amirsaam/main. \n  _add push notification entitlement_\n\n* Merge branch 'main' of https://github.com/amirsaam/hiddify-next. \n\n* Add config export on ios. \n\n* Fix ios connection status on app restart. \n\n* Add push notification entitlement. \n\n* Fix attempt. \n\n* Fix. \n\n* Fix ci again. \n\n* Fix ci tag matching. \n\n* Fix ci. \n\n* Change logger to print in console. \n\n* Change routing assets order. \n\n* Change options description. \n\n* Fix ci tag pattern. \n\n* Fix ci. \n\n* Change workflows. \n\n* Add missing es translations. \n\n* Inlang: update translations. \n\n* Fix infinite sub traffic. \n\n* Fix bugs. \n\n* Fix modal text alignment. \n\n* Merge pull request #329 from amirsaam/newMain. \n  _revert landscape mode_\n\n* Revert landscape mode. \n\n* Merge pull request #328 from amirsaam/main. \n  _remove unnecessary force unwrap, libcore linking add landscape mode_\n\n* Remove unnecessary force unwrap, libcore linking add landscape mode, \n\n* Change ios method error handling. \n\n* Fix bugs. \n\n* Remove custom_lint. \n\n* Add vscode launch config macos designed for ipad. \n\n* Fix ios flutter plugins. \n\n* Fix ios core name. \n\n* Merge pull request #323 from amirsaam/main. \n  _better fix for vpn connecting_\n\n* Better fix for vpn connecting. \n\n* Merge pull request #321 from amirsaam/main. \n  _match exportOptions identifiers with project_\n\n* Fixing not connecting to vpn. \n\n* Match exportOptions identifiers with project. \n\n* Merge pull request #319 from amirsaam/main. \n  _fix vpn profile not being created + changing run to release_\n\n* Fix vpn profile not being created + changing run to release. \n\n* Merge pull request #318 from amirsaam/main. \n  _ios fix?_\n\n* Ios fix? \n\n* Fix build. \n\n* Fix windows deep link. \n\n* Merge pull request #316 from amirsaam/main. \n  _Update pubspec.lock_\n\n* Update pubspec.lock. \n\n* Merge pull request #315 from amirsaam/main. \n  _add back cupertino_http_\n\n* Add back cupertino_http. \n\n* Update. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Update appcast. \n\n\n\n## v0.13.6 (2024-01-07)\n\n#### Other\n\n* Fix build. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Fix qr scanner links. \n\n* Update changelog. \n\n* Update core (sing-box v1.7.8) \n\n* Update dependencies. \n\n* Remove unused dependencies. \n\n* Refactor service wrappers. \n\n* Update. \n\n* Update ios. \n\n* Change default connection test url. \n\n* Fix android service mode switch. \n\n* Add profile fetch cancel. \n\n* Add update all subscriptions. \n\n* Fix profile update service. \n\n* Inlang: update translations. \n\n* Change app http client. \n\n* Inlang: update translations. \n\n* Fix bugs. \n\n* Add experimental flag to new config options. \n\n* Add connection from lan option. \n\n* Add dns routing option. \n\n* Add bypass lan option. \n\n* Fix profile edit with new url. \n\n* Change tls tricks settings section name. \n\n* Fix db migration bug. \n\n* Bump version. \n\n* Fix minor bugs. \n\n* Remove desktop auto connect. \n\n* Add experimental feature notice. \n\n* Update README.md. \n\n* Update README.md. \n\n* Fix multi instance on windows. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Update README_cn.md. \n\n* Update README_cn.md. \n  _Some proxy software such as clash do not have official Chinese names and use English by default._\n\n* Add experimental flag in settings ui. \n\n* Fix inlang setup. \n\n* Remove robocopy. \n\n* Fix build. \n\n* Fix windows portable again. \n\n* Update changelog. \n\n* Add android high refresh rate support. \n\n* Refactor desktop window management and tray. \n\n* Fix macOS restore from dock. \n\n* Add desktop shortcuts. \n\n\n\n## v0.12.3 (2023-12-28)\n\n#### Changes\n\n* Fix inconsistent channel naming. \n\n#### Fix\n\n* Set codec for stream handlers. \n\n* Ios launch bug. \n\n#### Other\n\n* Add Afghanistan region. \n\n* Fix packaging bug. \n\n* Fix windows packaging. \n\n* Fix bugs. \n\n* Change minimum macos version in docs. \n\n* Add version to desktop window. \n\n* [fix]: SettingsPickerDialog pop exception. \n\n* Update ios. \n\n* Ios: add /platform event channel. \n\n* Feat: Added stats stream for ios. \n\n* Feat: Added stats stream for ios. \n\n* Update ios. \n\n* Update ios. \n\n* Update ios. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Ios update. \n\n\n\n## v0.12.2 (2023-12-23)\n\n#### Other\n\n* Remove native http client (temporarily) \n\n* Update dependencies. \n\n* Update core (sing-box v1.7.6) \n\n* Fix bugs. \n\n* Update core (sing-box v1.7.5) \n\n* Change initialization and logging. \n\n\n\n## v0.12.1 (2023-12-21)\n\n#### Other\n\n* Fix preferences initialization error. \n\n* Bump android sdk version. \n\n* Fix android service mode. \n\n* Change privacy policy url. \n\n* Update appcast. \n\n\n\n## v0.12.0 (2023-12-20)\n\n#### New\n\n* Add support for hysteria and wg. \n\n* Add user-agent like clash sing-box for better compatibility. \n\n* Send all releases to beta by default. \n\n#### Fix\n\n* Bug in  windows portable. \n\n* Linux parse. \n\n#### Other\n\n* Add hiddify/iimport schema. \n\n* Fix chinese inlang url. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update changelog. \n\n* Change memory limit on desktop. \n\n* Remove locale name provider. \n\n* Fix service mode. \n\n* Add android dynamic notification. \n\n* Add android stats channel. \n\n* Fix translation generator. \n\n* Add config option reset. \n\n* Add missing routing asset warning. \n\n* Fix text input traversal. \n\n* Add basic d-pad support. \n\n* Fix tray initialization bug. \n\n* Update LICENSE.md. \n\n* Update LICENSE.md. \n\n* Update LICENSE.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README_cn.md. \n\n* Update README_ru.md. \n\n* Update README.md. \n\n* Add preferences migration. \n\n* Fix tray behavior. \n\n* Fix intro routing bug. \n\n* Fix macos build. \n\n* Fix macos name. \n\n* Fix macos icon. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update ios. \n\n* Update ios. \n\n* Update ios. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Fix build. \n\n* Change entrypoint. \n\n* Add TLS trick config options. \n\n* Update ios. \n\n* Update platform interface. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Update dev-i.yml. \n\n* Update dev-i.yml. \n\n* Update pubspec.yaml. \n\n* Create dev-i.yml. \n\n* Update changelog. \n\n* Update dependencies. \n\n* Update core (singbox v1.7) \n\n* Fix status mapper. \n\n* Refactor. \n\n* Refactor logs. \n\n* Remove unused clash api. \n\n* Update core (singbox 1.7.0-rc.2) \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Refactor router. \n\n* Refactor profiles. \n\n* Update changelog. \n\n* Fix chinese typography bug. \n\n* Add soffchen geo assets. \n\n* Refactor geo assets. \n\n* Update dependencies. \n\n* Bump ci sdk version. \n\n* Bump sdk version. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_cn.md. \n\n* Update README_ru.md. \n\n* Update README_ru.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update release_message.md. \n\n* Update appcast. \n\n* Merge pull request #189 from jomertix/main. \n  _Update ru strings_\n\n* Nothing changed strings_tr.i18n.json. \n\n* Nothing changed strings_fa.i18n.json. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Update. \n\n\n\n## v0.11.1 (2023-11-19)\n\n#### Other\n\n* Fix android manifest. \n\n* Fix documentation. \n\n* Update release_message.md. \n\n\n\n## v0.11.0 (2023-11-19)\n\n#### New\n\n* Add ic_launcher for android tv. \n\n* Publish dev release to seperate channel. \n\n* Add winget. \n\n* Add prepare to make file. \n\n#### Fix\n\n* Build-linux-libs. \n\n* Build. \n\n* Naming issue. \n\n* Winget release. \n\n* Action version. \n\n* Winget publish. \n\n* Build error. \n\n* No commit message. \n\n* Build. \n\n* Bug. \n\n* Build. \n\n* Distutils. \n\n* No commit message. \n\n#### Other\n\n* Change default direct dns. \n\n* Revert \"new: add ic_launcher for android tv\" \n  _This reverts commit 49bb62c8289d0885a762e01b7f0785690a7d3af7._\n\n* Change ir region rules. \n\n* Merge pull request #179 from betaxab/main. \n  _Update translations_\n\n* Inlang: update translations. \n\n* Add recommended geo assets. \n\n* Add error handling for geo assets. \n\n* Fix build. \n\n* Add geo assets settings. \n\n* Fix bug in strings_tr.i18n.json. \n\n* Merge pull request #173 from hasankarli/main. \n  _Update Turkish translations_\n\n* Inlang: update translations. \n\n* Merge pull request #169 from solokot/main. \n  _Update Russian translation_\n\n* Merge branch 'main' into main. \n\n* Merge pull request #168 from jomertix/main. \n  _inlang: update translations_\n\n* Inlang: update translations. \n\n* Merge pull request #172 from Locas56227/main. \n  _Fix and improve Chinese README_\n\n* Fix and improve Chinese README. \n\n* Update build.yml. \n\n* Update appcast. \n\n* Add navigation to system tray. \n\n* Update Russian translation. \n  _and partially revert ugly inlang changes_\n\n* Change http adapter. \n\n* Add independent dns cache option. \n\n* Fix bottom navigation bar accessibility. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update release_message.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Merge pull request #165 from huajizhige/main. \n  _Improve translation_\n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Update appcast. \n\n* Fix release command. \n\n* Add subscription qr code share. \n\n* Improve qr code scanner ux. \n\n* Fix code typo. \n\n* Ci: ignore appcast. \n\n* Merge pull request #164 from jomertix/main. \n  _Update ru string_\n\n* Update strings_ru.i18n.json. \n  _Fix translation_\n\n* Update strings_ru.i18n.json. \n  _Fix translate_\n\n* Merge pull request #162 from solokot/main. \n  _Update strings_ru_\n\n* Update strings_ru. \n  _Fix google translate_\n\n* Merge pull request #161 from Aloxaf/Aloxaf-patch-1. \n  _fix: build-linux-libs_\n\n* Add sub link share. \n\n* Fix bootstrap bug. \n\n* Add proxy tag dialog. \n\n* Add export config to clipboard. \n\n* Add geoassessts to makefile prepare. \n\n* Merge pull request #155 from solokot/main. \n  _Update strings_ru_\n\n* Update strings_ru. \n\n* Add service mode and strict route. \n\n* Add basic privilege check. \n\n* Fix ui bugs. \n\n* Remove unnecessary preferences. \n\n* Fix config preferences. \n\n* Update changelog. \n\n* Update core to v0.8.0. \n\n* Fix manual update checker. \n\n* Fix logs page scroll. \n\n* Fix android service restart. \n\n* Fix android service revoke. \n\n* Change toast. \n\n* Fix linting and cleanup. \n\n* Remove execute config as is. \n\n* Update dependencies. \n\n* Update README_cn.md. \n\n* Update README_cn.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Merge pull request #138 from huajizhige/main. \n  _inlang: update translations_\n\n* Inlang: update translations. \n\n* Update. \n\n* Fix. \n\n* Fix. \n\n* Test. \n\n* Merge pull request #137 from huajizhige/patch-1. \n  _Update README_cn.md_\n\n* Update README_cn.md. \n  _Improve translation_\n\n* Update README_cn.md. \n\n* Update README_cn.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_ru.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Fix. \n\n* Update. \n\n* Fix. \n\n* Fix build. \n\n* Add distutils. \n\n* Improve Android TV. \n\n* Update. \n\n* Add. \n\n* Fix appcast url. \n\n* Add appcast. \n\n* Add auto connect on start. \n\n* Merge pull request #123 from Nyar233/main. \n  _Update translations_\n\n* Inlang: update translations. \n\n* Update release_message.md. \n\n* Update release_message.md. \n\n* Merge pull request #115 from solokot/main. \n  _Update Russian: fix google translate_\n\n* Update Russian: fix google translate. \n\n* Merge pull request #113 from Nyar233/main. \n  _inlang: update translations_\n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Inlang: update translations. \n\n* Change system tray options. \n\n* Add core mode. \n\n* Add sidebar stats for large screens. \n\n* Update dependencies. \n\n* Change router for different screen size. \n\n* Merge pull request #108 from Hiiirad/patch-1. \n  _Update auto_translator.py to fix the Path Traversal Vulnerability_\n\n* Update auto_translator.py to fix the Path Traversal Vulnerability. \n\n\n\n## v0.10.0 (2023-10-27)\n\n#### New\n\n* Add ios core library to the project. \n\n#### Fix\n\n* Ipa. \n\n#### Other\n\n* Remove reconnect on auto profile update. \n\n* Update changelog. \n\n* Add selected tag for selector outbounds. \n\n* Add core debug flag. \n\n* Add url test delay color. \n\n* Change info logs. \n\n* Delete .github/help/linux/آموزش هیدیفای‌نکست فارسی لینوکس.desktop. \n\n* Delete .github/help/mac-windows/آموزش هیدیفای‌نکست فارسی.url. \n\n* Update dependencies. \n\n* Change pre release update checking off. \n\n* Add terms and privacy to about page. \n\n* Add memory limit option. \n\n* Change directory management. \n\n* Comment ios. \n\n* Change app id. \n\n* Merge pull request #98 from GFWFighter/main. \n  _Initial iOS version_\n\n* Merge pull request #1 from GFWFighter/ios. \n  _iOS_\n\n* Merge branch 'main' into ios. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Merge pull request #95 from solokot/main. \n  _Update Russian_\n\n* Update Russian. \n  _Mainly fix google translate of  new worlds_\n\n* Change logging. \n\n* Change changelog workflow. \n\n* Add russia region. \n\n* Change theme prefs. \n\n* Merge pull request #90 from solokot/main. \n  _Russian translation: fix some mistakes_\n\n* Russian translation: fix some mistakes. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Add rules. \n\n* Update LICENSE.md. \n\n* Inlang: update translations. \n\n* Merge pull request #85 from leic4u/main. \n  _Update README_cn.md_\n\n* Update README_cn.md. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Add inlang translations. \n\n* Add inlang project and remove localize. \n\n* Merge pull request #82 from Iam54r1n4/main. \n  _add inlang translator_\n\n* Update: fr_FR.json. \n\n* Add: french language. \n\n* Add: inlang translation files(incomplete) \n\n* Add: setup inlang translation. \n\n* Merge pull request #74 from lifeindarkside/patch-1. \n  _Update strings_ru.i18n.json_\n\n* Update strings_ru.i18n.json. \n  _Update some wrong interpretation_\n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README.md. \n\n* First working version. \n\n* Underlying VPN Logic. \n\n* Initialize Packet Tunnel + Config. \n\n* Update Tutorial_For_HiddifyNext_Linux.desktop. \n\n* Update Tutorial_For_HiddifyNext.url. \n\n* Update آموزش هیدیفای‌نکست فارسی.url. \n\n* Update آموزش هیدیفای‌نکست فارسی لینوکس.desktop. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n\n\n## v0.9.2 (2023-10-15)\n\n#### Other\n\n* Fix ndk setup. \n\n* Fix android arm bug. \n\n\n\n## v0.9.1 (2023-10-15)\n\n#### Other\n\n* Update README_cn.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Delete docs/file. \n\n* Google play badge. \n\n* Delete docs/google-play-badge1.png. \n\n* Upload google play badge. \n\n* Create file. \n\n* Delete docs/google-play-badge.png. \n\n* Fix ci. \n\n* Change ndk setup. \n\n* Update dependencies. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_ru.md. \n\n* Update README_ru.md. \n\n* Change desktop error handling. \n\n* Fix android bugs. \n\n* Update README.md. \n\n* Update README_cn.md. \n\n* Update README_ru.md. \n\n* Update README_ru.md. \n\n* Update README_cn.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Delete Russian_Flag.png. \n\n* Add Russian flag. \n\n* Delete docs/file. \n\n* Create README_ru.md. \n\n* Delete REAMME_ru.md. \n\n* Create REAMME_ru.md. \n\n* Update README_cn.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README_cn.md. \n\n* Update README_cn.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update file. \n\n* Uplaod a badge for google play. \n\n* Delete google-play-badge.png. \n\n* Add files via upload. \n\n* Create file. \n\n* Delete docs/google-play-badge.png. \n\n* Delete google-play-badge.png. \n\n* Add files via upload. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Create Chinese README_cn.md. \n\n\n\n## v0.8.12 (2023-10-13)\n\n#### Fix\n\n* Typo. \n\n* Bug. \n\n* Release names. \n\n#### Other\n\n* Update readme. \n\n* Update core. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Merge pull request #56 from solokot/main. \n  _Improvement of Russian translation_\n\n* Improvement of Russian translation. \n  _Basically a replacement for machine automatic translation_\n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Fix bugs. \n\n* Change android signing. \n\n* Update README.md. \n\n* Update readme. \n\n* Update contribution guide. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update release_message.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update release template. \n\n\n\n## v0.8.11 (2023-10-08)\n\n#### Changes\n\n* Remove auto release message. \n\n\n\n## v0.8.10 (2023-10-08)\n\n#### Fix\n\n* Release changelog. \n\n\n\n## v0.8.9 (2023-10-08)\n\n#### Fix\n\n* Missing libs. \n\n\n\n## v0.8.8 (2023-10-08)\n\n#### Fix\n\n* Release bug. \n\n\n\n## v0.8.7 (2023-10-08)\n\n#### Fix\n\n* Release message. \n\n\n\n## v0.8.6 (2023-10-08)\n\n#### Fix\n\n* Windows build. \n\n* Build issue. \n\n#### Other\n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Update release_message.md. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Update release_message.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Delete docs/note. \n\n* Add files via upload. \n\n* Create note. \n\n* Update contribute.md. \n\n* Update README.md. \n\n* Delete assets/images/google-play-badge.png. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update release_message.md. \n\n* Update release_message.md. \n\n* Update release_message.md. \n\n* Fix build. \n\n\n\n## v0.8.5 (2023-10-07)\n\n#### Fix\n\n* Bug. \n\n\n\n## v0.8.4 (2023-10-07)\n\n#### Fix\n\n* Translate. \n\n\n\n## v0.8.3 (2023-10-07)\n\n#### Other\n\n* Add release message  and help. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Fix bugs. \n\n* Update release_message.md. \n\n* Update release_message.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update release_message.md. \n\n* Update release_message.md. \n\n* Create release_message.md. \n\n* Add google play badge to assets. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Create contribute.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README_fa.md. \n\n* Add feature request template. \n\n* Fix issue template. \n\n* Add issue template. \n\n\n\n## v0.8.2 (2023-10-07)\n\n#### Fix\n\n* Hysteria2 and some links. \n\n#### Other\n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Create README_fa.md. \n\n* Update README.md. \n\n* Update README.md. \n\n* Update README.md. \n  _Add some features to the readme_\n\n* Add debug export to clipboard. \n\n\n\n## v0.8.1 (2023-10-06)\n\n#### New\n\n* Add chinese lang. \n\n#### Fix\n\n* Chinese translation. \n\n#### Other\n\n* Update core 0.5.1. \n\n* Fix floating number sub info header. \n\n* Add russian. \n\n* Add google play descriptions. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n\n\n## v0.8.0 (2023-10-05)\n\n#### New\n\n* Add russian lang. \n\n#### Other\n\n* Add proxy tag sanitization. \n\n* Fix bugs. \n\n* Add ignore app update version. \n\n* Add new protocols to link parser. \n\n* Auto update translations on release. \n\n* Update translation. \n\n* Remove param in ru translation. \n\n\n\n## v0.7.2 (2023-10-04)\n\n#### Other\n\n* Fix bugs. \n\n\n\n## v0.7.1 (2023-10-03)\n\n#### Other\n\n* Fix log and analytics bugs. \n\n\n\n## v0.7.0 (2023-10-03)\n\n#### New\n\n* Add support of some exception panel with zero usage. \n\n#### Other\n\n* Fix translation bug. \n\n* Improve error handling and presentation. \n\n* Add retry for network ops. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Add local profile. \n\n* Add auto translator. \n\n* Add auto translate. \n\n\n\n## v0.6.0 (2023-09-30)\n\n#### Other\n\n* Fix minor bugs. \n\n* Add scheduled profile update. \n\n* Update dependencies. \n\n* Refactor profile details page. \n\n\n\n## v0.5.11 (2023-09-22)\n\n#### Other\n\n* Fix android bundle abi. \n\n* Bump core version. \n\n\n\n## v0.5.10 (2023-09-22)\n\n#### Other\n\n* Fix minor bugs. \n\n* Fix profile update bug. \n\n\n\n## v0.5.9 (2023-09-22)\n\n#### Other\n\n* Add build number. \n\n\n\n## v0.5.8 (2023-09-22)\n\n#### New\n\n* Add crashlytics. \n\n* Add support for base64 sublink for header from content. \n\n* Add profile headers from comments in response! good for hosting in github and show information. \n\n* Automated version release. \n\n* Send release versions only to play market add pre-release version. \n\n#### Changes\n\n* Change invalid dns 235.5.5.5 to 8.8.8.8. \n\n#### Fix\n\n* Improve routing accessibility and logs. \n\n* Minor bugs. \n\n* Prefs persistence. \n\n* Crashlytics. \n\n* App update url. \n\n* Small profiles. \n\n* Makefile vars. \n\n* Adaptive icon. \n\n* Pre-release. \n\n* Typo in adaptive icon. \n\n* If .dev is exist in the version do not show update needed. \n\n* Keep the link as it is. fix the issue with & \n\n* Dependency issue. \n\n* Remove extra print. \n\n* Bug in get headers from body. \n\n* Bug ini ci to google play. \n\n* Tag version issue. \n\n* Ci bug. \n\n* Remove comments. \n\n* Bug. \n\n#### Other\n\n* Fix ci. \n\n* Fix false-positive error reports. \n\n* Change build setup. \n\n* Fix minor bugs. \n\n* Refactor app update. \n\n* Fix sentry dart plugin upload. \n\n* Fix ci debug symbols upload. \n\n* Add sentry provider observer. \n\n* Ci: add sentry debug info upload. \n\n* Update dependencies and general fixes. \n\n* Chore: bump agp version. \n\n* Ci: fix env. \n\n* Ci: add dsn env. \n\n* Feat: add region and terms to intro. \n\n* Update ci.yml. \n\n* Build: add sentry dsn. \n\n* Feat: add intro screen. \n\n* Feat: add sentry. \n\n* Ci: bump macos version. \n\n* Feat: update profile when adding preexisting url. \n\n* Publish draft even with error. \n\n* Update version of core. \n\n* Merge branch 'main' of hiddify-github:hiddify/hiddify-next. \n\n* Add firebase. \n\n* Update translation. \n\n* Refactor: version presentation. \n\n* Perf: improve header parser. \n\n* Feat: remove check for updates in market releases. \n\n* Better manage the market release. \n\n* Update. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Improve accessability. \n\n* Fix per-app proxy selection. \n\n* Add android per-app proxy. \n\n* Add basic flavors. \n\n* Update Makefile. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Update Makefile. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Update README.md. \n\n* Add accessability semantics. \n\n* Add support for fragment in the url. \n\n\n\n## v0.1.0 (2023-09-11)\n\n#### New\n\n* Add signing to android. \n\n* Add android universal build also. \n\n* Add change in network entitlements. \n\n* Change logo icon to next. \n\n* Add cache for speed up build process. \n\n* Add windows portable version. \n\n* Add libclash. \n\n* Add as draft release. \n\n* Make better ci and building applications. \n\n#### Changes\n\n* Change windows logo. \n\n* Change macos build  to flutter_distributor. \n\n* Remove x86 builds since flutter does not support. \n\n* Add x64 to the name. \n\n* Update makefile. \n\n#### Fix\n\n* Space bugs in some panels. \n\n* Aab. \n\n* Aab build. \n\n* Universal sign. \n\n* KeystoreProperties. \n\n* Name issue. \n\n* Revert package name change. \n\n* Name. \n\n* Geosite download. \n\n* Windows portable bug. \n\n* Change name bug. \n\n* Setup exe files. \n\n* Libclash.so. \n\n* Linux AppImage. \n\n* Error. \n\n* Category in linux. \n\n* Add fuse for linux. \n\n* Icon. \n\n* Linux logo. \n\n* Android. \n\n* Makefile error. \n\n#### Other\n\n* Release v0.1.0. \n\n* Fix ci build. \n\n* Update ci. \n\n* Add core version. \n\n* Fix barrel file. \n\n* Change proxies lifecycle. \n\n* Add service restart. \n\n* Remove notification service. \n\n* Change android notification permission. \n\n* Add android service restart. \n\n* Change mark new profile active. \n\n* Handle unlimited. \n\n* Update upload download link stats. \n\n* Update Translations. \n\n* Remove // TODO add content disposition parsing. \n\n* Add content-disposition for profile title. \n\n* Update README.md. \n\n* Add hysteria2. \n\n* Fix android build connection. \n\n* Add android connection shortcut. \n\n* Add desktop autostart. \n\n* Add android boot receiver. \n\n* Add android proxy service. \n\n* Add android battery optimizations settings. \n\n* Change sharedpreferences to unify with android. \n\n* Add vclibs. \n\n* Update dependencies. \n\n* Add submodule. \n\n* Fix translation code gen. \n\n* Change prefs. \n\n* Change default config options. \n\n* Remove string casing. \n\n* Update ci.yml. \n\n* Remove caching. \n\n* Change core prefs to use code generation. \n\n* Fix custom lint. \n\n* Fix general issues. \n\n* Remove vclibs. \n\n* Update README.md. \n\n* Fix blank screen. \n\n* Add proxies sort. \n\n* Refactor preferences. \n\n* Update dependencies. \n\n* Add more config options to settings. \n\n* Add tun implementation option. \n\n* Add android power manager. \n\n* Add android quick tile. \n\n* Fix macos dependencies. \n\n* Fix mac build. \n\n* Fix build. \n\n* Change system tray icon. \n\n* Fix riverpod code generation. \n\n* Remove unnecessary config options. \n\n* Add accessability semantics. \n\n* Update dependencies. \n\n* Add config options. \n\n* Add pref utilities. \n\n* Add stats overview. \n\n* Update Translations. \n\n* Fix android outbounds view. \n\n* Remove unnecessary options. \n\n* Change proxies flow. \n\n* Add android command client support. \n\n* Update README.md. \n\n* Add status command receiver. \n\n* Add hiddify deeplink. \n\n* Add macos deeplink support. \n\n* Add singbox deeplink. \n\n* Change error prompts. \n\n* Fix url parser. \n\n* Remove unnecessary prefs. \n\n* Update dependencies. \n\n* Make AppImage zipped for preserving permission in linux. \n\n* Add user agent. \n\n* Fix uri launch. \n\n* Update ci flutter version. \n\n* Fix macos silent start. \n\n* Change proxies page. \n\n* Fix desktop connection error msg. \n\n* Add button tooltips. \n\n* Fix logging. \n\n* Create dependabot.yml. \n\n* Create CODE_OF_CONDUCT.md. \n\n* Fix aab. \n\n* Add aab file. \n\n* Change windows-portable name to HiddifyNext-portable. \n\n* Add debug mode. \n\n* Add misc settings ui. \n\n* Remote unnecessary logs. \n\n* Add misc preferences. \n\n* Add directory options. \n\n* Fix linux build. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Fix android builds. \n\n* Fix android splash screen. \n\n* Update icons. \n\n* Fix windows executable build. \n\n* Remove unnecessary build steps. \n\n* Remove build number from appbar. \n\n* Update readme. \n\n* Change desktop directories. \n\n* Remove desktop notifications. \n\n* Force same version code for all platforms. \n\n* Add more logs. \n\n* Add log timestamp. \n\n* Update icons. \n\n* Remove drawer branding. \n\n* Add download section in readme. \n\n* Fix name of universal apk. \n\n* Fix order. \n\n* Update readme. \n\n* Update logging. \n\n* Update geo assets url. \n\n* Change linux directories. \n\n* Update icon. \n\n* Update icon. \n\n* Update logo for all platforms. \n\n* Revert name in macos. \n\n* Temporary disable app sandbox. \n\n* Change name. \n\n* Update Release.entitlements to fix binding issue. \n\n* Merge pull request #5 from evstegneych/main. \n  _add macos option_\n\n* Add macos option. \n\n* Update ci flutter version. \n\n* Update kotlin version. \n\n* Update other dependencies. \n\n* Update dependencies. \n\n* Update flutter version. \n\n* Update LICENSE.md. \n\n* Add build option for ios but not tested. \n\n* Return: build for all. \n\n* Fix build for macos. \n\n* Fix ci. \n\n* Migrate to singbox. \n\n* Fix routing. \n\n* Fix connection button text casing. \n\n* Add update checking. \n\n* Add separate page for clash overrides. \n\n* Add version number to appbar. \n\n* Add more icons. \n\n* Add sort limited profiles last. \n\n* Fix profile sort icon. \n\n* Fix profile traffic ratio. \n\n* Add profiles sort option. \n\n* Refactor profile addition flow. \n\n* Add extra profile metadata. \n\n* Fix linux deep link service. \n\n* Refactor profile tile. \n\n* Add locale based font. \n\n* Fix linux startup. \n\n* Update dependencies. \n\n* Add about page. \n\n* Fix linux notifications. \n\n* Build all. \n\n* Hard coding. \n\n* Add png. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Update Makefile. \n\n* Update ci.yml. \n\n* Update Makefile. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Update Makefile. \n\n* Update ci.yml. \n\n* Update Makefile. \n\n* Fix makefile. \n\n* Fix actions. \n\n* Fix actions. \n\n* Fix actions. \n\n* Update build setup. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Create LICENSE.md. \n\n* Add core submodule. \n\n* Remove core libs. \n\n* Update Makefile. \n\n* Update Makefile. \n\n* Remove c install. \n\n* Update make. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Add Persian font. \n\n* Update dependencies. \n\n* Update to libclash. \n\n* Add cache. \n\n* Add: new action. \n\n* Add write permission. \n\n* Fix. \n\n* Modify. \n\n* Fix. \n\n* Update. \n\n* Fix android build. \n\n* Fix code gen bug. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Fix CI. \n\n* Fix CI. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Fix CI. \n\n* Update ci.yml. \n\n* Update ci.yml. \n\n* Add CI. \n\n* Add silent start for desktop. \n\n* Update readme. \n\n* Add headless mode to desktop. \n\n* Update dependencies. \n\n* Add distribution setup for windows. \n\n* Add Farsi(fa) language. \n\n* Merge branch 'main' of https://github.com/hiddify/hiddify-next. \n\n* Initial commit. \n\n* Initial. \n\n\n\n"
  },
  {
    "path": "LICENSE.md",
    "content": "# Hiddify Extended GNU General Public License v3\n\nThe Hiddify project is licensed under GPL v3, with the following additional conditions in accordance with GPL v3 Section 7. Failure to comply with these terms may result in requests to app stores to remove or restrict access to your app.\n\n# Additional Conditions to GPL v3:\n1.\t**Source Code Availability:** If you use any part of this code, you must publish your source code on GitHub as a fork of the Hiddify repository and keep it up-to-date with any published app releases. Your repository should be shown as a fork of  https://github.com/hiddify/hiddify-app .\n2.\t**Automated Release:** All releases must be made using GitHub Actions.\n3.\t**Attribution:** You must give appropriate credit to Hiddify and https://github.com/hiddify/hiddify-app, link to the original license, and document any changes you have made in Readme.\n4.\t**No Malware:** Adding any malware to the app is strictly prohibited.\n5.\t**Naming and Interface Restrictions:** You are not allowed to  publish the app on any app store (e.g., AppStore, Google Play, F-Droid, Microsoft) with a name or user interface that closely resembles Hiddify (e.g., names like Hiddify, Hidy*, Hiddy*, *Ify or similar UI are prohibited).\n6.\t**NonCommercial Use Only:** You may not use this material for commercial purposes, including selling and advertising, without prior written consent.\n7.\t**ShareAlike Requirement:** If you remix, transform, or build upon the material, you must distribute your contributions under this same license as an open-source fork of https://github.com/hiddify/hiddify-app .\n\n \nGNU General Public License\n==========================\n\n_Version 3, 29 June 2007_  \n_Copyright © 2007 Free Software Foundation, Inc. &lt;<http://fsf.org/>&gt;_\n\nEveryone is permitted to copy and distribute verbatim copies of this license\ndocument, but changing it is not allowed.\n\n## Preamble\n\nThe GNU General Public License is a free, copyleft license for software and other\nkinds of works.\n\nThe licenses for most software and other practical works are designed to take away\nyour freedom to share and change the works. By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change all versions of a\nprogram--to make sure it remains free software for all its users. We, the Free\nSoftware Foundation, use the GNU General Public License for most of our software; it\napplies also to any other work released this way by its authors. You can apply it to\nyour programs, too.\n\nWhen we speak of free software, we are referring to freedom, not price. Our General\nPublic Licenses are designed to make sure that you have the freedom to distribute\ncopies of free software (and charge for them if you wish), that you receive source\ncode or can get it if you want it, that you can change the software or use pieces of\nit in new free programs, and that you know you can do these things.\n\nTo protect your rights, we need to prevent others from denying you these rights or\nasking you to surrender the rights. Therefore, you have certain responsibilities if\nyou distribute copies of the software, or if you modify it: responsibilities to\nrespect the freedom of others.\n\nFor example, if you distribute copies of such a program, whether gratis or for a fee,\nyou must pass on to the recipients the same freedoms that you received. You must make\nsure that they, too, receive or can get the source code. And you must show them these\nterms so they know their rights.\n\nDevelopers that use the GNU GPL protect your rights with two steps: **(1)** assert\ncopyright on the software, and **(2)** offer you this License giving you legal permission\nto copy, distribute and/or modify it.\n\nFor the developers' and authors' protection, the GPL clearly explains that there is\nno warranty for this free software. For both users' and authors' sake, the GPL\nrequires that modified versions be marked as changed, so that their problems will not\nbe attributed erroneously to authors of previous versions.\n\nSome devices are designed to deny users access to install or run modified versions of\nthe software inside them, although the manufacturer can do so. This is fundamentally\nincompatible with the aim of protecting users' freedom to change the software. The\nsystematic pattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable. Therefore, we have designed\nthis version of the GPL to prohibit the practice for those products. If such problems\narise substantially in other domains, we stand ready to extend this provision to\nthose domains in future versions of the GPL, as needed to protect the freedom of\nusers.\n\nFinally, every program is threatened constantly by software patents. States should\nnot allow patents to restrict development and use of software on general-purpose\ncomputers, but in those that do, we wish to avoid the special danger that patents\napplied to a free program could make it effectively proprietary. To prevent this, the\nGPL assures that patents cannot be used to render the program non-free.\n\nThe precise terms and conditions for copying, distribution and modification follow.\n\n## TERMS AND CONDITIONS\n\n### 0. Definitions\n\n“This License” refers to version 3 of the GNU General Public License.\n\n“Copyright” also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n“The Program” refers to any copyrightable work licensed under this\nLicense. Each licensee is addressed as “you”. “Licensees” and\n“recipients” may be individuals or organizations.\n\nTo “modify” a work means to copy from or adapt all or part of the work in\na fashion requiring copyright permission, other than the making of an exact copy. The\nresulting work is called a “modified version” of the earlier work or a\nwork “based on” the earlier work.\n\nA “covered work” means either the unmodified Program or a work based on\nthe Program.\n\nTo “propagate” a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for infringement under\napplicable copyright law, except executing it on a computer or modifying a private\ncopy. Propagation includes copying, distribution (with or without modification),\nmaking available to the public, and in some countries other activities as well.\n\nTo “convey” a work means any kind of propagation that enables other\nparties to make or receive copies. Mere interaction with a user through a computer\nnetwork, with no transfer of a copy, is not conveying.\n\nAn interactive user interface displays “Appropriate Legal Notices” to the\nextent that it includes a convenient and prominently visible feature that **(1)**\ndisplays an appropriate copyright notice, and **(2)** tells the user that there is no\nwarranty for the work (except to the extent that warranties are provided), that\nlicensees may convey the work under this License, and how to view a copy of this\nLicense. If the interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n### 1. Source Code\n\nThe “source code” for a work means the preferred form of the work for\nmaking modifications to it. “Object code” means any non-source form of a\nwork.\n\nA “Standard Interface” means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of interfaces\nspecified for a particular programming language, one that is widely used among\ndevelopers working in that language.\n\nThe “System Libraries” of an executable work include anything, other than\nthe work as a whole, that **(a)** is included in the normal form of packaging a Major\nComponent, but which is not part of that Major Component, and **(b)** serves only to\nenable use of the work with that Major Component, or to implement a Standard\nInterface for which an implementation is available to the public in source code form.\nA “Major Component”, in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system (if any) on which\nthe executable work runs, or a compiler used to produce the work, or an object code\ninterpreter used to run it.\n\nThe “Corresponding Source” for a work in object code form means all the\nsource code needed to generate, install, and (for an executable work) run the object\ncode and to modify the work, including scripts to control those activities. However,\nit does not include the work's System Libraries, or general-purpose tools or\ngenerally available free programs which are used unmodified in performing those\nactivities but which are not part of the work. For example, Corresponding Source\nincludes interface definition files associated with source files for the work, and\nthe source code for shared libraries and dynamically linked subprograms that the work\nis specifically designed to require, such as by intimate data communication or\ncontrol flow between those subprograms and other parts of the work.\n\nThe Corresponding Source need not include anything that users can regenerate\nautomatically from other parts of the Corresponding Source.\n\nThe Corresponding Source for a work in source code form is that same work.\n\n### 2. Basic Permissions\n\nAll rights granted under this License are granted for the term of copyright on the\nProgram, and are irrevocable provided the stated conditions are met. This License\nexplicitly affirms your unlimited permission to run the unmodified Program. The\noutput from running a covered work is covered by this License only if the output,\ngiven its content, constitutes a covered work. This License acknowledges your rights\nof fair use or other equivalent, as provided by copyright law.\n\nYou may make, run and propagate covered works that you do not convey, without\nconditions so long as your license otherwise remains in force. You may convey covered\nworks to others for the sole purpose of having them make modifications exclusively\nfor you, or provide you with facilities for running those works, provided that you\ncomply with the terms of this License in conveying all material for which you do not\ncontrol copyright. Those thus making or running the covered works for you must do so\nexclusively on your behalf, under your direction and control, on terms that prohibit\nthem from making any copies of your copyrighted material outside their relationship\nwith you.\n\nConveying under any other circumstances is permitted solely under the conditions\nstated below. Sublicensing is not allowed; section 10 makes it unnecessary.\n\n### 3. Protecting Users' Legal Rights From Anti-Circumvention Law\n\nNo covered work shall be deemed part of an effective technological measure under any\napplicable law fulfilling obligations under article 11 of the WIPO copyright treaty\nadopted on 20 December 1996, or similar laws prohibiting or restricting circumvention\nof such measures.\n\nWhen you convey a covered work, you waive any legal power to forbid circumvention of\ntechnological measures to the extent such circumvention is effected by exercising\nrights under this License with respect to the covered work, and you disclaim any\nintention to limit operation or modification of the work as a means of enforcing,\nagainst the work's users, your or third parties' legal rights to forbid circumvention\nof technological measures.\n\n### 4. Conveying Verbatim Copies\n\nYou may convey verbatim copies of the Program's source code as you receive it, in any\nmedium, provided that you conspicuously and appropriately publish on each copy an\nappropriate copyright notice; keep intact all notices stating that this License and\nany non-permissive terms added in accord with section 7 apply to the code; keep\nintact all notices of the absence of any warranty; and give all recipients a copy of\nthis License along with the Program.\n\nYou may charge any price or no price for each copy that you convey, and you may offer\nsupport or warranty protection for a fee.\n\n### 5. Conveying Modified Source Versions\n\nYou may convey a work based on the Program, or the modifications to produce it from\nthe Program, in the form of source code under the terms of section 4, provided that\nyou also meet all of these conditions:\n\n* **a)** The work must carry prominent notices stating that you modified it, and giving a\nrelevant date.\n* **b)** The work must carry prominent notices stating that it is released under this\nLicense and any conditions added under section 7. This requirement modifies the\nrequirement in section 4 to “keep intact all notices”.\n* **c)** You must license the entire work, as a whole, under this License to anyone who\ncomes into possession of a copy. This License will therefore apply, along with any\napplicable section 7 additional terms, to the whole of the work, and all its parts,\nregardless of how they are packaged. This License gives no permission to license the\nwork in any other way, but it does not invalidate such permission if you have\nseparately received it.\n* **d)** If the work has interactive user interfaces, each must display Appropriate Legal\nNotices; however, if the Program has interactive interfaces that do not display\nAppropriate Legal Notices, your work need not make them do so.\n\nA compilation of a covered work with other separate and independent works, which are\nnot by their nature extensions of the covered work, and which are not combined with\nit such as to form a larger program, in or on a volume of a storage or distribution\nmedium, is called an “aggregate” if the compilation and its resulting\ncopyright are not used to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit. Inclusion of a covered work in an aggregate\ndoes not cause this License to apply to the other parts of the aggregate.\n\n### 6. Conveying Non-Source Forms\n\nYou may convey a covered work in object code form under the terms of sections 4 and\n5, provided that you also convey the machine-readable Corresponding Source under the\nterms of this License, in one of these ways:\n\n* **a)** Convey the object code in, or embodied in, a physical product (including a\nphysical distribution medium), accompanied by the Corresponding Source fixed on a\ndurable physical medium customarily used for software interchange.\n* **b)** Convey the object code in, or embodied in, a physical product (including a\nphysical distribution medium), accompanied by a written offer, valid for at least\nthree years and valid for as long as you offer spare parts or customer support for\nthat product model, to give anyone who possesses the object code either **(1)** a copy of\nthe Corresponding Source for all the software in the product that is covered by this\nLicense, on a durable physical medium customarily used for software interchange, for\na price no more than your reasonable cost of physically performing this conveying of\nsource, or **(2)** access to copy the Corresponding Source from a network server at no\ncharge.\n* **c)** Convey individual copies of the object code with a copy of the written offer to\nprovide the Corresponding Source. This alternative is allowed only occasionally and\nnoncommercially, and only if you received the object code with such an offer, in\naccord with subsection 6b.\n* **d)** Convey the object code by offering access from a designated place (gratis or for\na charge), and offer equivalent access to the Corresponding Source in the same way\nthrough the same place at no further charge. You need not require recipients to copy\nthe Corresponding Source along with the object code. If the place to copy the object\ncode is a network server, the Corresponding Source may be on a different server\n(operated by you or a third party) that supports equivalent copying facilities,\nprovided you maintain clear directions next to the object code saying where to find\nthe Corresponding Source. Regardless of what server hosts the Corresponding Source,\nyou remain obligated to ensure that it is available for as long as needed to satisfy\nthese requirements.\n* **e)** Convey the object code using peer-to-peer transmission, provided you inform\nother peers where the object code and Corresponding Source of the work are being\noffered to the general public at no charge under subsection 6d.\n\nA separable portion of the object code, whose source code is excluded from the\nCorresponding Source as a System Library, need not be included in conveying the\nobject code work.\n\nA “User Product” is either **(1)** a “consumer product”, which\nmeans any tangible personal property which is normally used for personal, family, or\nhousehold purposes, or **(2)** anything designed or sold for incorporation into a\ndwelling. In determining whether a product is a consumer product, doubtful cases\nshall be resolved in favor of coverage. For a particular product received by a\nparticular user, “normally used” refers to a typical or common use of\nthat class of product, regardless of the status of the particular user or of the way\nin which the particular user actually uses, or expects or is expected to use, the\nproduct. A product is a consumer product regardless of whether the product has\nsubstantial commercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n“Installation Information” for a User Product means any methods,\nprocedures, authorization keys, or other information required to install and execute\nmodified versions of a covered work in that User Product from a modified version of\nits Corresponding Source. The information must suffice to ensure that the continued\nfunctioning of the modified object code is in no case prevented or interfered with\nsolely because modification has been made.\n\nIf you convey an object code work under this section in, or with, or specifically for\nuse in, a User Product, and the conveying occurs as part of a transaction in which\nthe right of possession and use of the User Product is transferred to the recipient\nin perpetuity or for a fixed term (regardless of how the transaction is\ncharacterized), the Corresponding Source conveyed under this section must be\naccompanied by the Installation Information. But this requirement does not apply if\nneither you nor any third party retains the ability to install modified object code\non the User Product (for example, the work has been installed in ROM).\n\nThe requirement to provide Installation Information does not include a requirement to\ncontinue to provide support service, warranty, or updates for a work that has been\nmodified or installed by the recipient, or for the User Product in which it has been\nmodified or installed. Access to a network may be denied when the modification itself\nmaterially and adversely affects the operation of the network or violates the rules\nand protocols for communication across the network.\n\nCorresponding Source conveyed, and Installation Information provided, in accord with\nthis section must be in a format that is publicly documented (and with an\nimplementation available to the public in source code form), and must require no\nspecial password or key for unpacking, reading or copying.\n\n### 7. Additional Terms\n\n“Additional permissions” are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions. Additional\npermissions that are applicable to the entire Program shall be treated as though they\nwere included in this License, to the extent that they are valid under applicable\nlaw. If additional permissions apply only to part of the Program, that part may be\nused separately under those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\nWhen you convey a copy of a covered work, you may at your option remove any\nadditional permissions from that copy, or from any part of it. (Additional\npermissions may be written to require their own removal in certain cases when you\nmodify the work.) You may place additional permissions on material, added by you to a\ncovered work, for which you have or can give appropriate copyright permission.\n\nNotwithstanding any other provision of this License, for material you add to a\ncovered work, you may (if authorized by the copyright holders of that material)\nsupplement the terms of this License with terms:\n\n* **a)** Disclaiming warranty or limiting liability differently from the terms of\nsections 15 and 16 of this License; or\n* **b)** Requiring preservation of specified reasonable legal notices or author\nattributions in that material or in the Appropriate Legal Notices displayed by works\ncontaining it; or\n* **c)** Prohibiting misrepresentation of the origin of that material, or requiring that\nmodified versions of such material be marked in reasonable ways as different from the\noriginal version; or\n* **d)** Limiting the use for publicity purposes of names of licensors or authors of the\nmaterial; or\n* **e)** Declining to grant rights under trademark law for use of some trade names,\ntrademarks, or service marks; or\n* **f)** Requiring indemnification of licensors and authors of that material by anyone\nwho conveys the material (or modified versions of it) with contractual assumptions of\nliability to the recipient, for any liability that these contractual assumptions\ndirectly impose on those licensors and authors.\n\nAll other non-permissive additional terms are considered “further\nrestrictions” within the meaning of section 10. If the Program as you received\nit, or any part of it, contains a notice stating that it is governed by this License\nalong with a term that is a further restriction, you may remove that term. If a\nlicense document contains a further restriction but permits relicensing or conveying\nunder this License, you may add to a covered work material governed by the terms of\nthat license document, provided that the further restriction does not survive such\nrelicensing or conveying.\n\nIf you add terms to a covered work in accord with this section, you must place, in\nthe relevant source files, a statement of the additional terms that apply to those\nfiles, or a notice indicating where to find the applicable terms.\n\nAdditional terms, permissive or non-permissive, may be stated in the form of a\nseparately written license, or stated as exceptions; the above requirements apply\neither way.\n\n### 8. Termination\n\nYou may not propagate or modify a covered work except as expressly provided under\nthis License. Any attempt otherwise to propagate or modify it is void, and will\nautomatically terminate your rights under this License (including any patent licenses\ngranted under the third paragraph of section 11).\n\nHowever, if you cease all violation of this License, then your license from a\nparticular copyright holder is reinstated **(a)** provisionally, unless and until the\ncopyright holder explicitly and finally terminates your license, and **(b)** permanently,\nif the copyright holder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\nMoreover, your license from a particular copyright holder is reinstated permanently\nif the copyright holder notifies you of the violation by some reasonable means, this\nis the first time you have received notice of violation of this License (for any\nwork) from that copyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\nTermination of your rights under this section does not terminate the licenses of\nparties who have received copies or rights from you under this License. If your\nrights have been terminated and not permanently reinstated, you do not qualify to\nreceive new licenses for the same material under section 10.\n\n### 9. Acceptance Not Required for Having Copies\n\nYou are not required to accept this License in order to receive or run a copy of the\nProgram. Ancillary propagation of a covered work occurring solely as a consequence of\nusing peer-to-peer transmission to receive a copy likewise does not require\nacceptance. However, nothing other than this License grants you permission to\npropagate or modify any covered work. These actions infringe copyright if you do not\naccept this License. Therefore, by modifying or propagating a covered work, you\nindicate your acceptance of this License to do so.\n\n### 10. Automatic Licensing of Downstream Recipients\n\nEach time you convey a covered work, the recipient automatically receives a license\nfrom the original licensors, to run, modify and propagate that work, subject to this\nLicense. You are not responsible for enforcing compliance by third parties with this\nLicense.\n\nAn “entity transaction” is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an organization, or\nmerging organizations. If propagation of a covered work results from an entity\ntransaction, each party to that transaction who receives a copy of the work also\nreceives whatever licenses to the work the party's predecessor in interest had or\ncould give under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if the predecessor\nhas it or can get it with reasonable efforts.\n\nYou may not impose any further restrictions on the exercise of the rights granted or\naffirmed under this License. For example, you may not impose a license fee, royalty,\nor other charge for exercise of rights granted under this License, and you may not\ninitiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging\nthat any patent claim is infringed by making, using, selling, offering for sale, or\nimporting the Program or any portion of it.\n\n### 11. Patents\n\nA “contributor” is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based. The work thus\nlicensed is called the contributor's “contributor version”.\n\nA contributor's “essential patent claims” are all patent claims owned or\ncontrolled by the contributor, whether already acquired or hereafter acquired, that\nwould be infringed by some manner, permitted by this License, of making, using, or\nselling its contributor version, but do not include claims that would be infringed\nonly as a consequence of further modification of the contributor version. For\npurposes of this definition, “control” includes the right to grant patent\nsublicenses in a manner consistent with the requirements of this License.\n\nEach contributor grants you a non-exclusive, worldwide, royalty-free patent license\nunder the contributor's essential patent claims, to make, use, sell, offer for sale,\nimport and otherwise run, modify and propagate the contents of its contributor\nversion.\n\nIn the following three paragraphs, a “patent license” is any express\nagreement or commitment, however denominated, not to enforce a patent (such as an\nexpress permission to practice a patent or covenant not to sue for patent\ninfringement). To “grant” such a patent license to a party means to make\nsuch an agreement or commitment not to enforce a patent against the party.\n\nIf you convey a covered work, knowingly relying on a patent license, and the\nCorresponding Source of the work is not available for anyone to copy, free of charge\nand under the terms of this License, through a publicly available network server or\nother readily accessible means, then you must either **(1)** cause the Corresponding\nSource to be so available, or **(2)** arrange to deprive yourself of the benefit of the\npatent license for this particular work, or **(3)** arrange, in a manner consistent with\nthe requirements of this License, to extend the patent license to downstream\nrecipients. “Knowingly relying” means you have actual knowledge that, but\nfor the patent license, your conveying the covered work in a country, or your\nrecipient's use of the covered work in a country, would infringe one or more\nidentifiable patents in that country that you have reason to believe are valid.\n\nIf, pursuant to or in connection with a single transaction or arrangement, you\nconvey, or propagate by procuring conveyance of, a covered work, and grant a patent\nlicense to some of the parties receiving the covered work authorizing them to use,\npropagate, modify or convey a specific copy of the covered work, then the patent\nlicense you grant is automatically extended to all recipients of the covered work and\nworks based on it.\n\nA patent license is “discriminatory” if it does not include within the\nscope of its coverage, prohibits the exercise of, or is conditioned on the\nnon-exercise of one or more of the rights that are specifically granted under this\nLicense. You may not convey a covered work if you are a party to an arrangement with\na third party that is in the business of distributing software, under which you make\npayment to the third party based on the extent of your activity of conveying the\nwork, and under which the third party grants, to any of the parties who would receive\nthe covered work from you, a discriminatory patent license **(a)** in connection with\ncopies of the covered work conveyed by you (or copies made from those copies), or **(b)**\nprimarily for and in connection with specific products or compilations that contain\nthe covered work, unless you entered into that arrangement, or that patent license\nwas granted, prior to 28 March 2007.\n\nNothing in this License shall be construed as excluding or limiting any implied\nlicense or other defenses to infringement that may otherwise be available to you\nunder applicable patent law.\n\n### 12. No Surrender of Others' Freedom\n\nIf conditions are imposed on you (whether by court order, agreement or otherwise)\nthat contradict the conditions of this License, they do not excuse you from the\nconditions of this License. If you cannot convey a covered work so as to satisfy\nsimultaneously your obligations under this License and any other pertinent\nobligations, then as a consequence you may not convey it at all. For example, if you\nagree to terms that obligate you to collect a royalty for further conveying from\nthose to whom you convey the Program, the only way you could satisfy both those terms\nand this License would be to refrain entirely from conveying the Program.\n\n### 13. Use with the GNU Affero General Public License\n\nNotwithstanding any other provision of this License, you have permission to link or\ncombine any covered work with a work licensed under version 3 of the GNU Affero\nGeneral Public License into a single combined work, and to convey the resulting work.\nThe terms of this License will continue to apply to the part which is the covered\nwork, but the special requirements of the GNU Affero General Public License, section\n13, concerning interaction through a network will apply to the combination as such.\n\n### 14. Revised Versions of this License\n\nThe Free Software Foundation may publish revised and/or new versions of the GNU\nGeneral Public License from time to time. Such new versions will be similar in spirit\nto the present version, but may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number. If the Program specifies that\na certain numbered version of the GNU General Public License “or any later\nversion” applies to it, you have the option of following the terms and\nconditions either of that numbered version or of any later version published by the\nFree Software Foundation. If the Program does not specify a version number of the GNU\nGeneral Public License, you may choose any version ever published by the Free\nSoftware Foundation.\n\nIf the Program specifies that a proxy can decide which future versions of the GNU\nGeneral Public License can be used, that proxy's public statement of acceptance of a\nversion permanently authorizes you to choose that version for the Program.\n\nLater license versions may give you additional or different permissions. However, no\nadditional obligations are imposed on any author or copyright holder as a result of\nyour choosing to follow a later version.\n\n### 15. Disclaimer of Warranty\n\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\nEXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER\nEXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE\nQUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE\nDEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n### 16. Limitation of Liability\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY\nCOPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS\nPERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,\nINCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\nPROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE\nOR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE\nWITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n### 17. Interpretation of Sections 15 and 16\n\nIf the disclaimer of warranty and limitation of liability provided above cannot be\ngiven local legal effect according to their terms, reviewing courts shall apply local\nlaw that most closely approximates an absolute waiver of all civil liability in\nconnection with the Program, unless a warranty or assumption of liability accompanies\na copy of the Program in return for a fee.\n\n_END OF TERMS AND CONDITIONS_\n\n## How to Apply These Terms to Your New Programs\n\nIf you develop a new program, and you want it to be of the greatest possible use to\nthe public, the best way to achieve this is to make it free software which everyone\ncan redistribute and change under these terms.\n\nTo do so, attach the following notices to the program. It is safest to attach them\nto the start of each source file to most effectively state the exclusion of warranty;\nand each file should have at least the “copyright” line and a pointer to\nwhere the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program does terminal interaction, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type 'show c' for details.\n\nThe hypothetical commands `show w` and `show c` should show the appropriate parts of\nthe General Public License. Of course, your program's commands might be different;\nfor a GUI interface, you would use an “about box”.\n\nYou should also get your employer (if you work as a programmer) or school, if any, to\nsign a “copyright disclaimer” for the program, if necessary. For more\ninformation on this, and how to apply and follow the GNU GPL, see\n&lt;<http://www.gnu.org/licenses/>&gt;.\n\nThe GNU General Public License does not permit incorporating your program into\nproprietary programs. If your program is a subroutine library, you may consider it\nmore useful to permit linking proprietary applications with the library. If this is\nwhat you want to do, use the GNU Lesser General Public License instead of this\nLicense. But first, please read\n&lt;<http://www.gnu.org/philosophy/why-not-lgpl.html>&gt;.\n"
  },
  {
    "path": "Makefile",
    "content": "# .ONESHELL:\ninclude dependencies.properties\n\n# --- Log Colors ---\nblue   := \\033[1;34m\ngreen  := \\033[1;92m\nyellow := \\033[1;33m\nreset  := \\033[0m\n# --- Log helpers ---\n# Usage: $(BLUE) <text> $(DONE)\nBLUE   := echo -e \"$(blue)\nGREEN  := echo -e \"$(green)\nYELLOW := echo -e \"$(yellow)\nDONE := $(reset)\"\n\nMKDIR := mkdir -p\nRM  := rm -rf\nSEP :=/\n\nifeq ($(OS),Windows_NT)\n    ifeq ($(IS_GITHUB_ACTIONS),)\n\t\t# MKDIR := -mkdir\n\t\tRM := rmdir /s /q\n\t\t# SEP:=\\\\\n\tendif\nendif\n\n\n# Define sed command based on the OS\nifeq ($(OS),Windows_NT)\n    # Windows (Assume Git Bash or similar sed is available, or standard syntax)\n    SED := sed -i\nelse\n\tifeq ($(shell uname),Darwin) # macOS\n    \tSED :=sed -i ''\n\telse # Linux\n    \tSED :=sed -i\n\tendif\nendif\n\n\nBINDIR=hiddify-core$(SEP)bin\nANDROID_OUT=android$(SEP)app$(SEP)libs\nIOS_OUT=ios$(SEP)Frameworks\nDESKTOP_OUT=hiddify-core$(SEP)bin\nGEO_ASSETS_DIR=assets$(SEP)core\n\nCORE_PRODUCT_NAME=hiddify-core\nCORE_NAME=hiddify-lib\nLIB_NAME=hiddify-core\n\nifeq ($(CHANNEL),prod)\n\tCORE_URL=https://github.com/hiddify/hiddify-next-core/releases/download/v$(core.version)\nelse\n\tCORE_URL=https://github.com/hiddify/hiddify-next-core/releases/download/draft\nendif\n\nifeq ($(CHANNEL),prod)\n\tTARGET=lib/main_prod.dart\nelse\n\tTARGET=lib/main.dart\nendif\n\nBUILD_ARGS=--dart-define sentry_dsn=$(SENTRY_DSN)\nDISTRIBUTOR_ARGS=--skip-clean --build-target $(TARGET) --build-dart-define sentry_dsn=$(SENTRY_DSN)\n\n\n\nget:\t\n\tflutter pub get\n\ngen:\n\tdart run build_runner build --delete-conflicting-outputs\n\ntranslate:\n\tdart run slang\n\n\n\nprepare:\n\t@echo use the following commands to prepare the library for each platform:\n\t@echo    make android-prepare\n\t@echo    make windows-prepare\n\t@echo    make linux-prepare \n\t@echo    make macos-prepare\n\t@echo    make ios-prepare\n\ncommon-prepare:  get gen translate\nwindows-prepare: common-prepare windows-libs\n\t\nios-prepare: common-prepare ios-libs \n\tcd ios; pod repo update; pod install;echo \"done ios prepare\"\n\t\nmacos-prepare: common-prepare macos-libs\nlinux-prepare: common-prepare linux-amd64-libs\n\n\nlinux-amd64-prepare: common-prepare linux-amd64-libs\nlinux-arm64-prepare: common-prepare linux-arm64-libs\nlinux-amd64-musl-prepare: common-prepare linux-amd64-musl-libs\nlinux-arm64-musl-prepare: common-prepare linux-arm64-musl-libs\n\n\nlinux-appimage-prepare:linux-prepare\nlinux-rpm-prepare:linux-prepare\nlinux-deb-prepare:linux-prepare\n\nandroid-prepare:common-prepare android-libs\t\nandroid-apk-prepare:android-prepare\nandroid-aab-prepare:android-prepare\n\n.PHONY: generate_kotlin_protos\ngenerate_kotlin_protos: \n\t# Run protoc to generate Kotlin files\n\t# protoc \\\n\t# \t--proto_path=hiddify-core/ \\\n\t# \t--java_out=./android/app/src/main/java/ \\\n\t# \t--grpc-java_out=./android/app/src/main/java/ \\\n\t# \t$(shell find hiddify-core/v2 hiddify-core/extension -name \"*.proto\")\n\trsync -av --delete \\\n\t\t--include='*/' \\\n\t\t--include='*.proto' \\\n\t\t--exclude='*' \\\n\t\thiddify-core/v2 hiddify-core/extension ./android/app/src/main/protos/\n\t# # Find .proto files and update package declarations\n\t# find \"./android/app/src/main/java/com/hiddify/hiddify/protos\" -type f -name \"*.java\" | while read -r proto_file; do \\\n\t#     if grep -q \"^package \" \"$$proto_file\"; then \\\n\t#         $(SED) 's/^package \\([\\w\\.]*\\)/package com.hiddify.hiddify.protos.\\1/g' \"$$proto_file\"; \\\n\t#     fi \\\n\t# done\n\ngenerate_go_protoc:\n\tmake -C hiddify-core -f Makefile protos\n\techo \"SED: $(SED)\"\ngenerate_dart_protoc:\n\tmkdir -p lib/hiddifycore/generated\n\tprotoc --dart_out=grpc:lib/hiddifycore/generated --proto_path=hiddify-core/  $(shell find hiddify-core/v2 hiddify-core/extension -name \"*.proto\") \tgoogle/protobuf/timestamp.proto ; \\\n\n.PHONY: protos\nprotos: generate_go_protoc generate_kotlin_protos generate_dart_protoc\n\t\n\t\n\t\n\nmacos-install-deps:\n\tbrew install create-dmg tree \n\tnpm install -g appdmg\n\tdart pub global activate fastforge\n\nios-install-deps: \n\tif [ \"$(flutter)\" = \"true\" ]; then \\\n\t\tcurl -L -o ~/Downloads/flutter_macos_3.19.3-stable.zip https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_3.22.3-stable.zip; \\\n\t\tmkdir -p ~/develop; \\\n\t\tcd ~/develop; \\\n\t\tunzip ~/Downloads/flutter_macos_3.22.3-stable.zip; \\\n\t\texport PATH=\"$$PATH:$$HOME/develop/flutter/bin\"; \\\n\t\techo 'export PATH=\"$$PATH:$$HOME/develop/flutter/bin\"' >> ~/.zshrc; \\\n\t\texport PATH=\"$PATH:$HOME/develop/flutter/bin\"; \\\n\t\techo 'export PATH=\"$PATH:$HOME/develop/flutter/bin\"' >> ~/.zshrc; \\\n\t\tcurl -sSL https://rvm.io/mpapis.asc | gpg --import -; \\\n\t\tcurl -sSL https://rvm.io/pkuczynski.asc | gpg --import -; \\\n\t\tcurl -sSL https://get.rvm.io | bash -s stable; \\\n\t\tbrew install openssl@1.1; \\\n\t\tPKG_CONFIG_PATH=$(brew --prefix openssl@1.1)/lib/pkgconfig rvm install 2.7.5; \\\n\t\tsudo gem install cocoapods -V; \\\n\tfi\n\tbrew install create-dmg tree \n\tnpm install -g appdmg\n\t\n\tdart pub global activate fastforge\n\t\n\nandroid-install-deps: \n\tdart pub global activate fastforge\nandroid-apk-install-deps: android-install-deps\nandroid-aab-install-deps: android-install-deps\n# loads the package list from linux_deps.list\nLINUX_DEPS = $(shell grep -vE '^\\s*#|^\\s*$$' linux_deps.list)\n# reads the Flutter version from pubspec.yaml\nREQUIRED_VER = $(shell sed -n '/environment:/,/flutter:/ s/.*flutter:[[:space:]]*//p' pubspec.yaml | tr -d \" '^\\\"\")\n\nlinux-amd64-install-deps:linux-install-deps\nlinux-amd64-musl-install-deps:linux-install-deps\nlinux-arm64-install-deps:linux-install-deps\nlinux-arm64-musl-install-deps:linux-install-deps\n\nlinux-install-deps:\n\t@$(BLUE)Installing Debian/Ubuntu dependencies...$(DONE)\n\tsudo apt-get update -y\n\tsudo apt-get install -y $(LINUX_DEPS)\n#\tloading fuce kernel module\n\t@$(BLUE)Loading fuce kernel module$(DONE)\n\tsudo modprobe fuse\n# \ttools for appimage\n\t@$(BLUE)Installing appimagetool$(DONE)\n\tif [ \"$$(uname -m)\" = \"aarch64\" ]; then \\\n\t\twget -O /tmp/appimagetool \"https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-aarch64.AppImage\"; \\\n\telse \\\n\t\twget -O /tmp/appimagetool \"https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage\"; \\\n\tfi\n\tchmod +x /tmp/appimagetool\n\tsudo mv /tmp/appimagetool /usr/local/bin/\n#   cloning flutter sdk\n\t@$(BLUE)Cloning Flutter SDK$(DONE); \\\n\tmkdir -p ~/develop; \\\n\tcd ~/develop; \\\n\t\\\n\tif [ ! -d \"flutter/.git\" ]; then \\\n\t\t$(BLUE)Flutter not found. cloning stable channel$(DONE); \\\n\t\trm -rf flutter; \\\n\t\tgit clone https://github.com/flutter/flutter.git -b stable flutter; \\\n\tfi; \\\n\t\\\n\tgit config --global --add safe.directory $$HOME/develop/flutter; \\\n\t\\\n\texport PATH=\"$$HOME/develop/flutter/bin:$$PATH\"; \\\n\tif ! grep -q 'flutter/bin' ~/.bashrc; then \\\n\t\techo 'export PATH=\"$$HOME/develop/flutter/bin:$$PATH\"' >> ~/.bashrc; \\\n\tfi\n# \tsyncing flutter version\n\t$(MAKE) linux-flutter-sync\n# \tinstalling fastforge https://pub.dev/packages/fastforge\n\t@$(BLUE)Installing fastforge$(DONE); \\\n\texport PATH=\"$$HOME/develop/flutter/bin:$$HOME/.pub-cache/bin:$$PATH\"; \\\n\tif ! grep -q '.pub-cache/bin' ~/.bashrc; then \\\n\t\techo 'export PATH=\"$$HOME/.pub-cache/bin:$$PATH\"' >> ~/.bashrc; \\\n\tfi; \\\n\tdart pub global activate fastforge; \\\n\tdart pub global activate protoc_plugin; \\\n\techo \"\"; \\\n\techo \"============================================================\"; \\\n\techo \"NOTE: After first setup, use the following command to update the PATH\"; \\\n\techo \"source ~/.bashrc\"; \\\n\techo \"============================================================\"\n\n# \tsyncing 'flutter sdk' version with pubspec.yaml flutter version\nlinux-flutter-sync:\n\t@$(BLUE)Syncing Flutter version with pubspec.yaml flutter version$(DONE); \\\n\texport PATH=\"$$HOME/develop/flutter/bin:$$PATH\"; \\\n\t$(BLUE)Downloading Flutter SDK components...$(DONE); \\\n\tflutter --version > /dev/null; \\\n\t\\\n\t$(BLUE)Checking Flutter version...$(DONE); \\\n\tCURRENT_VER=$$(flutter --version | head -n 1 | awk '{print $$2}'); \\\n\t$(BLUE)Target: $(REQUIRED_VER) | Current: $$CURRENT_VER$(DONE); \\\n\t\\\n\tif [ \"$$CURRENT_VER\" != \"$(REQUIRED_VER)\" ]; then \\\n\t\t$(BLUE)Version mismatch! switching to $(REQUIRED_VER)...$(DONE); \\\n\t\tcd ~/develop/flutter; \\\n\t\tgit fetch --tags; \\\n\t\tgit checkout $(REQUIRED_VER); \\\n\t\t$(BLUE)Switched to $(REQUIRED_VER)$(DONE); \\\n\t\tflutter doctor; \\\n\telse \\\n\t\t$(GREEN)Flutter SDK is ready.$(DONE); \\\n\tfi\n\nwindows-install-deps:\n\tdart pub global activate fastforge\n# \tchoco install innosetup -y\n\t\ngen_translations: #generating missing translations using google translate\n\tcd .github && bash sync_translate.sh\n\tmake translate\n\nandroid-release: android-apk-release android-aab-release\n\nandroid-apk-release:\n\tfastforge package \\\n\t  --platform android \\\n\t  --targets apk \\\n\t  --skip-clean \\\n\t  --build-target=$(TARGET) \\\n\t  --build-target-platform=android-arm,android-arm64,android-x64 \\\n\t  --build-dart-define=sentry_dsn=$(SENTRY_DSN)\n\tls -R build/app/outputs\n\nandroid-aab-release:\n\tfastforge package \\\n\t  --platform android \\\n\t  --targets aab \\\n\t  --skip-clean \\\n\t  --build-target=$(TARGET) \\\n\t  --build-dart-define=sentry_dsn=$(SENTRY_DSN) \\\n\t  --build-dart-define=release=google-play\n\nwindows-release: windows-zip-release windows-exe-release windows-msix-release\n\nwindows-zip-release:\n\tfastforge package \\\n\t  --platform windows \\\n\t  --targets zip \\\n\t  --skip-clean \\\n\t  --build-target=$(TARGET) \\\n\t  --build-dart-define=sentry_dsn=$(SENTRY_DSN) \\\n\t  --build-dart-define=portable=true\n\t@FULL_PATH=$$(ls dist/*/*.zip | head -n 1); \\\n\tZIP_DIR=$$(dirname \"$$FULL_PATH\"); \\\n\tZIP_FILE=$$(basename \"$$FULL_PATH\"); \\\n\tFILE_NAME=$${ZIP_FILE%.*}; \\\n\t$(YELLOW)Post-processing Windows portable$(DONE); \\\n\tcd \"$$ZIP_DIR\"; \\\n\t$(BLUE)Extracting and Repacking...$(DONE); \\\n\tmkdir -p Hiddify; \\\n\tunzip -q \"$$ZIP_FILE\" -d Hiddify/; \\\n\trm \"$$ZIP_FILE\"; \\\n\ttar -a -cf \"$$FILE_NAME.zip\" Hiddify; \\\n\trm -rf Hiddify; \\\n\t$(GREEN)Successful$(DONE)\n\nwindows-exe-release:\n\tfastforge package \\\n\t  --platform windows \\\n\t  --targets exe \\\n\t  --skip-clean \\\n\t  --build-target=$(TARGET) \\\n\t  --build-dart-define=sentry_dsn=$(SENTRY_DSN)\n\nwindows-msix-release:\n\tfastforge package \\\n\t  --platform windows \\\n\t  --targets msix \\\n\t  --skip-clean \\\n\t  --build-target=$(TARGET) \\\n\t  --build-dart-define=sentry_dsn=$(SENTRY_DSN)\n\nlinux-release: linux-deb-release linux-appimage-release\n\nlinux-amd64-release: linux-release\nlinux-arm64-release: linux-release\nlinux-amd64-musl-release: linux-release \nlinux-arm64-musl-release: linux-release\n\n\nlinux-deb-release:\n\tfastforge package \\\n\t--platform linux \\\n\t--targets deb \\\n\t--skip-clean \\\n\t--build-target=$(TARGET) \\\n\t--build-dart-define=sentry_dsn=$(SENTRY_DSN)\n\n\n# ==============================================================================\n# REFERENCE: MANUAL LIBRARY BUNDLING (INJECTION)\n# ==============================================================================\n# Use this method only if you need to manually force specific shared libraries \n# (e.g., libcurl.so.4) into the AppImage bundle.\n#\n# IMPLEMENTATION STEPS:\n#\n# 1. PRE-BUILD SCRIPT (Add to Makefile before build command):\n#    Create a temporary directory and copy the target library there.\n#    ---------------------------------------------------------------------------\n#    mkdir -p linux/bundled_libs\n#    cp /usr/lib/x86_64-linux-gnu/libcurl.so.4 linux/bundled_libs/\n#    ---------------------------------------------------------------------------\n#\n# 2. CMAKE CONFIGURATION (Add to linux/CMakeLists.txt):\n#    Instruct CMake to include the copied file in the final bundle.\n#    ---------------------------------------------------------------------------\n#    install(FILES \"${CMAKE_CURRENT_SOURCE_DIR}/bundled_libs/libcurl.so.4\"\n#       DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\n#       COMPONENT Runtime)\n#    ---------------------------------------------------------------------------\n#\n# ! WARNING !\n# This approach is generally DISCOURAGED. Manually bundling libraries can lead to\n# \"Dependency Hell,\" where bundled libs conflict with system libraries or have\n# their own unresolved dependencies. It increases maintenance cost and may cause\n# runtime instability. Use only for specific edge cases where standard linking fails.\n# ==============================================================================\nlinux-appimage-release:\n\tfastforge package \\\n\t--platform linux \\\n\t--targets appimage \\\n\t--skip-clean \\\n\t--build-target=$(TARGET) \\\n\t--build-dart-define=sentry_dsn=$(SENTRY_DSN)\n\t@$(YELLOW)Post-processing AppImage$(DONE); \\\n\t$(BLUE)Extracting AppImage$(DONE); \\\n\tcd dist/* && ./*.AppImage --appimage-extract > /dev/null; \\\n\t$(BLUE)Replacing AppRun$(DONE); \\\n\tcp ../../linux/packaging/appimage/AppRun squashfs-root/AppRun; \\\n\t$(BLUE)Granting permissions$(DONE); \\\n\tchmod +x squashfs-root/AppRun; \\\n\t$(BLUE)Adding StartupWMClass to hiddify.desktop$(DONE); \\\n\tsed -i '/^\\[Desktop Entry\\]/a StartupWMClass=app.hiddify.com' \"squashfs-root/hiddify.desktop\"; \\\n\t$(BLUE)Removing old AppImage$(DONE); \\\n\trm *.AppImage; \\\n\t$(BLUE)Deleting bundled libstdc++ to fix Arch Linux compatibility...$(DONE); \\\n\tfind squashfs-root/usr/lib -name \"libstdc++.so.6\" -delete; \\\n\t$(BLUE)Rebuilding AppImage$(DONE); \\\n\tARCH=x86_64 appimagetool --no-appstream squashfs-root Hiddify.AppImage > /dev/null; \\\n\t$(BLUE)Cleaning up squashfs$(DONE); \\\n\trm -rf squashfs-root; \\\n\t$(YELLOW)Creating Portable Package$(DONE); \\\n\tPKG_DIR_NAME=\"hiddify-linux-appimage\"; \\\n\t$(BLUE)Creating dir: $$PKG_DIR_NAME$(DONE); \\\n\tmkdir -p \"$$PKG_DIR_NAME\"; \\\n\t$(BLUE)Moving Hiddify.AppImage$(DONE); \\\n\tcp -p \"Hiddify.AppImage\" \"$$PKG_DIR_NAME/Hiddify.AppImage\"; \\\n\t$(BLUE)Creating Portable Home directory$(DONE); \\\n\tmkdir -p \"$$PKG_DIR_NAME/Hiddify.AppImage.home\"; \\\n\t$(BLUE)Compressing to .tar.gz$(DONE); \\\n\ttar -czf \"$$PKG_DIR_NAME.tar.gz\" -C . \"$$PKG_DIR_NAME\"; \\\n\t$(BLUE)Removing intermediate directory$(DONE); \\\n\trm -rf \"$$PKG_DIR_NAME\"; \\\n\t$(GREEN)Successful$(DONE)\n\nDOCKER_IMAGE_NAME := hiddify-linux-builder\nDOCKER_FLUTTER_VOL := hiddify-flutter-sdk-cache\nDOCKER_PUB_VOL := hiddify-pub-cache\n\nifeq ($(OS),Windows_NT)\n    FIX_OWNERSHIP := echo \\\"Windows detected: Skipping chown\\\"\nelse\n    FIX_OWNERSHIP := chown -R $(shell id -u):$(shell id -g) /host/dist_docker\nendif\n\nDOCKER_CMD := \\\n\tset -e; \\\n\techo '** Copying source code to container...'; \\\n\tmkdir -p /app; \\\n\tcp -r /host/. /app/; \\\n\tcd /app; \\\n\tmake linux-flutter-sync; \\\n\tmake linux-prepare; \\\n\techo '** Building Release (linux-release)...'; \\\n\tmake linux-release; \\\n\techo '** Copying artifacts to host...'; \\\n\trm -rf /host/dist_docker; \\\n\tif [ -d \\\"dist\\\" ]; then \\\n\t\tcp -r dist /host/dist_docker; \\\n\t\techo '** Fixing permissions for dist_docker...'; \\\n\t\t$(FIX_OWNERSHIP); \\\n\telse \\\n\t\techo 'Error: dist folder not found!'; \\\n\t\texit 1; \\\n\tfi;\n\nlinux-docker-release:\n\t@$(BLUE)Cleaning main project to reduce context size$(DONE)\n\tflutter clean\n\t\n\t@$(BLUE)Building docker image (Cached)$(DONE)\n\tdocker build -t $(DOCKER_IMAGE_NAME) -f Dockerfile .\n\t\n\t@$(BLUE)Ensuring cache volumes exist$(DONE)\n\tdocker volume create $(DOCKER_FLUTTER_VOL) || true\n\tdocker volume create $(DOCKER_PUB_VOL) || true\n\n\t@$(YELLOW)Running build inside container$(DONE)\n\t@docker run --rm \\\n\t\t-v \"$(CURDIR)://host\" \\\n\t\t-v $(DOCKER_FLUTTER_VOL)://root/develop/flutter \\\n\t\t-v $(DOCKER_PUB_VOL)://root/.pub-cache \\\n\t\t-e APPIMAGE_EXTRACT_AND_RUN=1 \\\n\t\t$(DOCKER_IMAGE_NAME) \\\n\t\t//bin/bash -c \"$(DOCKER_CMD)\"\n\n\t@$(GREEN)Successful. Output is in 'dist_docker' folder.$(DONE)\n\nmacos-release:\n\tfastforge package --platform macos --targets dmg,pkg $(DISTRIBUTOR_ARGS)\n\nios-release: #not tested\n\tfastforge package --platform ios --targets ipa --build-export-options-plist  ios/exportOptions.plist $(DISTRIBUTOR_ARGS)\n\nandroid-libs:\n\t$(MKDIR) $(ANDROID_OUT) || echo Folder already exists. Skipping...\n\tcurl -L $(CORE_URL)/$(CORE_NAME)-android.tar.gz | tar xz -C $(ANDROID_OUT)/\n\nandroid-apk-libs: android-libs\nandroid-aab-libs: android-libs\n\nwindows-libs:\n\t$(MKDIR) $(DESKTOP_OUT) || echo Folder already exists. Skipping...\n\tcurl -L $(CORE_URL)/$(CORE_NAME)-windows-amd64.tar.gz | tar xz -C $(DESKTOP_OUT)/\n\tls $(DESKTOP_OUT) || dir $(DESKTOP_OUT)/\n\t\n\nlinux-amd64-libs:\n\tmkdir -p $(DESKTOP_OUT)\n\tcurl -L $(CORE_URL)/$(CORE_NAME)-linux-amd64.tar.gz | tar xz -C $(DESKTOP_OUT)/\n\nlinux-arm64-libs:\n\tmkdir -p $(DESKTOP_OUT)\n\tcurl -L $(CORE_URL)/$(CORE_NAME)-linux-arm64.tar.gz | tar xz -C $(DESKTOP_OUT)/\n\nlinux-amd64-musl-libs:\n\tmkdir -p $(DESKTOP_OUT)\n\tcurl -L $(CORE_URL)/$(CORE_NAME)-linux-amd64-musl.tar.gz | tar xz -C $(DESKTOP_OUT)/\n\nlinux-arm64-musl-libs:\n\tmkdir -p $(DESKTOP_OUT)\n\tcurl -L $(CORE_URL)/$(CORE_NAME)-linux-arm64-musl.tar.gz | tar xz -C $(DESKTOP_OUT)/\n\n\nmacos-libs:\n\tmkdir -p  $(DESKTOP_OUT) \n\tcurl -L $(CORE_URL)/$(CORE_NAME)-macos.tar.gz | tar xz -C $(DESKTOP_OUT)\n\nios-libs: #not tested\n\tmkdir -p $(IOS_OUT)\n\trm -rf $(IOS_OUT)/HiddifyCore.xcframework\n\tcurl -L $(CORE_URL)/$(CORE_NAME)-ios.tar.gz | tar xz -C \"$(IOS_OUT)\"\n\nget-geo-assets:\n\techo \"\"\n\t# curl -L https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db -o $(GEO_ASSETS_DIR)/geoip.db\n\t# curl -L https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db -o $(GEO_ASSETS_DIR)/geosite.db\n\nbuild-headers:\n\tmake -C hiddify-core -f Makefile headers && mv $(BINDIR)/$(CORE_NAME)-headers.h $(BINDIR)/hiddify-core.h\n\nbuild-android-libs:\n\tmake -C hiddify-core -f Makefile android \n\tmv $(BINDIR)/$(LIB_NAME).aar $(ANDROID_OUT)/\n\nbuild-windows-libs:\n\tmake -C hiddify-core -f Makefile windows-amd64\n\nbuild-linux-libs:\n\tmake -C hiddify-core -f Makefile linux-amd64 \n\nbuild-macos-libs:\n\tmake -C hiddify-core -f Makefile macos\n\nbuild-ios-libs: \n\trm -rf $(IOS_OUT)/HiddifyCore.xcframework \n\tmake -C hiddify-core -f Makefile ios  \n\tmv $(BINDIR)/HiddifyCore.xcframework $(IOS_OUT)/HiddifyCore.xcframework\n\nrelease: # Create a new tag for release.\n\t@CORE_VERSION=$(core.version) bash -c \".github/change_version.sh \"\n\n\n\nios-temp-prepare: \n\tmake ios-prepare\n\tflutter build ios-framework\n\tcd ios\n\tpod install\n\t"
  },
  {
    "path": "README.md",
    "content": "<div dir=\"ltr\" align=center>\n    \n[**![Lang_farsi](https://user-images.githubusercontent.com/125398461/234186932-52f1fa82-52c6-417f-8b37-08fe9250a55f.png) فارسی**](README_fa.md) / [**Русский 🇷🇺**](README_ru.md) / [**简体中文 🇨🇳**](README_cn.md) / [**日本語 🇯🇵**](README_ja.md) / [**Portugês-BR 🇧🇷**](README_br.md)\n\n</div>\n<br>\n\n<p align=\"center\"><img src=\"https://github.com/hiddify/hiddify.com/blob/main/docs/assets/hiddify-app-logo.svg\" width=56% /></p>\n<br>\n\n<div align=\"center\">\n\n<!--\n![Hiddify logo + text](https://github.com/hiddify/hiddify-app/assets/125398461/d821cfe0-b4c4-441f-be4e-eb9209f59542)\n    -->\n    \n[![GP-Intalls](https://img.shields.io/endpoint?color=green&logo=google-play&logoColor=green&url=https%3A%2F%2Fplay.cuzi.workers.dev%2Fplay%3Fi%3Dapp.hiddify.com%26l%3DGoogle%2520Play%26m%3D%24shortinstalls&style=flat-square)](https://play.google.com/store/apps/details?id=app.hiddify.com) [![Downloads](https://img.shields.io/github/downloads/hiddify/hiddify-next/total?style=flat-square&logo=github)](https://github.com/hiddify/hiddify-app/releases/)[![Last Version](https://img.shields.io/github/release/hiddify/hiddify-next/all.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![Last Release Date](https://img.shields.io/github/release-date/hiddify/hiddify-next.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![commits](https://img.shields.io/github/commit-activity/m/hiddify/hiddify-next?style=flat-square)](https://github.com/hiddify/hiddify-app/)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board/5)\n\n</div>\n\n\n\n\n## What is Hiddify app?\n\n<p dir=\"ltr\" style=\"font-size: 16px\">A multi-platform proxy client based on <a href=\"https://github.com/SagerNet/sing-box\">Sing-box</a> universal proxy tool-chain. Hiddify offers a wide range of capabilities, like automatic node selection, TUN mode, remote profiles etc. Hiddify is ad-free and open-source. With support for a wide range of protocols, it provides a secure and private way for accessing free internet.</p>\n\n<div align=center>\n<img width=90% alt=\"English Demo\" src=\"https://github.com/hiddify/hiddify-app/assets/125398461/ffe5346d-3404-470f-b5e0-4364e23743d2\">\n\n</div>\n\n## 🚀 Main features\n\n✈️ Multi-platform: Android, iOS, Windows, macOS and Linux\n\n⭐ Intuitive and accessible UI\n\n🔍 Delay based node selection\n\n🟡 Wide range of protocols:\nVless, Vmess, Reality, TUIC, Hysteria, Wireguard, SSH etc.\n\n🟡 Subscription link and configuration formats: Sing-box, V2ray, Clash, Clash meta\n\n🔄 Automatic subscription update\n\n🔎 Display profile information including remaining days and traffic usage\n\n🛡 Open source, secure and community driven\n\n🌙 Dark and light modes\n\n⚙ Compatible with all proxy management panels\n\n⭐ Appropriate configuration for Iran, China, Russia and other countries\n\n📱 Available on official stores\n\n## 🛍️ Get It On Stores\n<a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532?platform=iphone\"><img height=50px src=\"https://github.com/user-attachments/assets/a7c62126-07ce-4f18-8197-bbb672f6d8be\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"https://play.google.com/store/apps/details?id=app.hiddify.com\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/blob/main/docs/google-play-badge.png\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"https://apps.microsoft.com/detail/Hiddify/9pdfnl3qv2s5?mode=mini\" target=\"_blank\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/assets/125398461/620750bb-4459-41b5-9f86-ba82119345b8\" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n\n\n## 📥 Direct Download\n\n<div align=left>\n<table>\n    <thead align=left>\n        <tr>\n            <th>OS</th>\n            <th>Download</th>\n        </tr>\n    </thead>\n    <tbody align=left>\n        <tr>\n        <td>iOS</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-iOS.ipa\"><img src=\"https://img.shields.io/badge/IPA-Universal-c0c0c0.svg?logo=ios\"></a>\n            </td>\n        </tr>\n        <tr>\n        <td>Android</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-universal.apk\"><img src=\"https://img.shields.io/badge/APK-Universal-044d29.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm64.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv8-168039.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm7.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv7-45bf55.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-x86_64.apk\"><img src=\"https://img.shields.io/badge/APK-x64-96ed89.svg?logo=android\"></a>\n            </td>\n        </tr>\n        <tr>\n            <td>Windows</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.Msix\"><img src=\"https://img.shields.io/badge/OfficialSetup-x64-0078d7.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.exe\"><img src=\"https://img.shields.io/badge/Setup-x64-2d7d9a.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Portable-x64.zip\"><img src=\"https://img.shields.io/badge/Portable-x64-67b7d1.svg?logo=windows\"></a>\n            </td>\n        </tr>\n        <tr>\n            <td>macOS</td>\n            <td>\n                <a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532\"><img src=\"https://img.shields.io/badge/IPA-ARM-D33A54.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS.dmg\"><img src=\"https://img.shields.io/badge/DMG-Universal-ea005e.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS-Installer.pkg\"><img src=\"https://img.shields.io/badge/PKG-Universal-bc544b.svg?logo=apple\" /></a>\n            </td>\n        </tr>\n        <tr>\n            <td>Linux</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Linux-x64.AppImage\"><img src=\"https://img.shields.io/badge/AppImage-x64-f84e29.svg?logo=linux\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Debian-x64.deb\"><img src=\"https://img.shields.io/badge/DebPackage-x64-FF9966.svg?logo=debian\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-rpm-x64.rpm\"><img src=\"https://img.shields.io/badge/RpmPackage-x64-F1B42F.svg?logo=redhat\"> </a>\n            </td>\n        </tr>\n    </tbody>\n</table>\n\n\n</div>\n\n## ⚙️ Installation and tutorials\n\n**Find tutorial information on our wiki page by clicking on image below.**\n\n<div align=\"center\">\n\n[![Tutorials on Wiki](https://github.com/hiddify/hiddify-app/assets/125398461/95bb5cf8-c143-4934-87d6-b9d4c31e035e)](https://hiddify.com/app/)\n\n\n</div>\n\n## 🌎 Translations\n\n    \nYou can improve existing languages or contribute new ones either by editing the JSON files in `/assets/translations` or [![Translate with Inlang](https://img.shields.io/badge/%20-%20-3ECF8E?logo=i18next&logoColor=white)](https://fink.inlang.com/github.com/hiddify/hiddify-app) by using [Inlang online editor](https://fink.inlang.com/github.com/hiddify/hiddify-app).    \n\n\n## ✏️ Acknowledgements\n\nWe would like to express our sincere appreciation to the contributors of the following projects, whose robust foundation and innovative features have significantly enhanced the success and functionality of this project.\n\n- [Sing-box](https://github.com/SagerNet/sing-box)\n- [Sing-box for Android](https://github.com/SagerNet/sing-box-for-android)\n- [Sing-box for Apple](https://github.com/SagerNet/sing-box-for-apple)\n- [Clash](https://github.com/Dreamacro/clash)\n- [Clash Meta](https://github.com/MetaCubeX/Clash.Meta)\n- [FClash](https://github.com/Fclash/Fclash)\n- [Vazirmatn Font by Saber Rastikerdar](https://github.com/rastikerdar/vazirmatn)\n- [Others](./pubspec.yaml)\n\n## 🎯 Donation and Support\n\nThe easiest way to support us is to click on the star (⭐) at the top of this page.\n\n<div align=center>\n    \n<a href=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history?repo_id=643504282\" target=\"_blank\" style=\"display: block\" align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=dark\" width=\"721\" height=\"auto\">\n    <img alt=\"Star History of hiddify/hiddify-app\" src=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=light\" width=\"721\" height=\"auto\">\n  </picture>\n</a>\n\n</div>\n\nWe also need financial support for our services. All of our activities are done voluntarily and financial support will be spent on the development of the project. You can view our support addresses [here](https://hiddify.com/donation-and-support/).\n\n## 👩‍🏫 Collaboration and Contact Information\n\nHiddify is a community driven project. If you're interested in contributing, please read the [contribution guidelines](./CONTRIBUTING.md). We would specially appreciate any help we can get in these areas: **Flutter, Go, iOS development (Swift), Android development (Kotlin).**\n\n<div align=center>\n\n<br>\n\n[![Email](https://img.shields.io/badge/Email-contribute@hiddify.com-005FF9?style=flat-square&logo=mail.ru)](mailto:contribute@hiddify.com)\n[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)\n[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)\n[![Twitter](https://img.shields.io/twitter/follow/hiddify_com?color=%231DA1F2&logo=twitter&logoColor=1DA1F2&style=flat-square)](https://twitter.com/intent/follow?screen_name=hiddify_com)\n\n</div>\n\n<p align=center>\n We appreciate all people who are participating in this project. Some people here and many many more outside of Github. It means a lot to us. ♥\n </p>\n \n<p align=center> \n<a href=\"https://github.com/hiddify/hiddify-app/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=hiddify/hiddify-next\" />\n</a>\n</p>\n<p align=center>\n Made with <a rel=\"\" target=\"_blank\" href=\"https://contrib.rocks\">Contrib.Rocks</a> \n</p>\n\n\n\n\n\n\n\n"
  },
  {
    "path": "README_br.md",
    "content": "<div dir=\"ltr\" align=center>\n    \n[**![Lang_farsi](https://user-images.githubusercontent.com/125398461/234186932-52f1fa82-52c6-417f-8b37-08fe9250a55f.png) فارسی**](README_fa.md) / [**English 🇺🇸**](README.md) / [**Русский 🇷🇺**](README_ru.md) / [**简体中文 🇨🇳**](README_cn.md) / [**日本語 🇯🇵**](README_ja.md)\n\n\n</div>\n<br>\n\n<p align=\"center\"><img src=\"https://github.com/hiddify/hiddify.com/blob/main/docs/assets/hiddify-app-logo.svg\" width=56% /></p>\n<br>\n\n<div align=\"center\">\n\n<!--\n![Hiddify logo + text](https://github.com/hiddify/hiddify-app/assets/125398461/d821cfe0-b4c4-441f-be4e-eb9209f59542)\n    -->\n    \n[![GP-Intalls](https://img.shields.io/endpoint?color=green&logo=google-play&logoColor=green&url=https%3A%2F%2Fplay.cuzi.workers.dev%2Fplay%3Fi%3Dapp.hiddify.com%26l%3DGoogle%2520Play%26m%3D%24shortinstalls&style=flat-square)](https://play.google.com/store/apps/details?id=app.hiddify.com) [![Downloads](https://img.shields.io/github/downloads/hiddify/hiddify-next/total?style=flat-square&logo=github)](https://github.com/hiddify/hiddify-app/releases/)[![Last Version](https://img.shields.io/github/release/hiddify/hiddify-next/all.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![Last Release Date](https://img.shields.io/github/release-date/hiddify/hiddify-next.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![commits](https://img.shields.io/github/commit-activity/m/hiddify/hiddify-next?style=flat-square)](https://github.com/hiddify/hiddify-app/)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board/5)\n\n</div>\n\n\n\n## O que é Hiddify app?\n\n<p dir=\"ltr\" style=\"font-size: 16px\">Um cliente de proxy multiplataforma baseado na ferramenta de proxy universal <a href=\"https://github.com/SagerNet/sing-box\">Sing-box</a>. O Hiddify oferece uma ampla gama de recursos, como seleção automática de nós, modo TUN, perfis remotos, etc. O Hiddify é livre de anúncios e de código aberto. Com suporte para uma ampla variedade de protocolos, ele oferece uma maneira segura e privada de acessar a internet gratuitamente.</p>\n\n<div align=center>\n<img width=90% alt=\"English Demo\" src=\"https://github.com/hiddify/hiddify-app/assets/125398461/ffe5346d-3404-470f-b5e0-4364e23743d2\">\n\n</div>\n\n## 🚀 Principais recursos\n\n✈️ Multiplataforma: Android, iOS, Windows, macOS e Linux\n\n⭐ Interface intuitiva e acessível\n\n🔍 Seleção de nós baseada em atraso\n\n🟡 Amplas opções de protocolos:\nVless, Vmess, Reality, TUIC, Hysteria, Wireguard, SSH, etc.\n\n🟡 Links de assinatura e formatos de configuração: Sing-box, V2ray, Clash, Clash meta\n\n🔄 Atualização automática de assinatura\n\n🔎 Exibição de informações do perfil, incluindo dias restantes e uso de tráfego\n\n🛡 Código aberto, seguro e impulsionado pela comunidade\n\n🌙 Modos escuro e claro\n\n⚙ Compatível com todos os painéis de gerenciamento de proxy\n\n⭐ Configuração adequada para Irã, China, Rússia e outros países\n\n📱 Disponível nas lojas oficiais\n\n## 🛍️ Obtenha nas lojas\n\n<a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532?platform=iphone\"><img height=50px src=\"https://github.com/user-attachments/assets/a7c62126-07ce-4f18-8197-bbb672f6d8be\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n<a href=\"https://play.google.com/store/apps/details?id=app.hiddify.com\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/blob/main/docs/google-play-badge.png\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n<a href=\"https://apps.microsoft.com/detail/Hiddify/9pdfnl3qv2s5?mode=mini\" target=\"_blank\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/assets/125398461/620750bb-4459-41b5-9f86-ba82119345b8\" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n\n\n## 📥 Download direto\n\n<div align=left>\n<table>\n    <thead align=left>\n        <tr>\n            <th>Sistema Operacional</th>\n            <th>Download</th>\n        </tr>\n    </thead>\n    <tbody align=left>\n        <tr>\n            <td>iOS</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-iOS.ipa\"><img src=\"https://img.shields.io/badge/IPA-Universal-c0c0c0.svg?logo=ios\"></a>\n            </td>\n        </tr>\n        <tr>\n        <td>Android</td><td>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-universal.apk\"><img src=\"https://img.shields.io/badge/APK-Universal-044d29.svg?logo=android\"></a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm64.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv8-168039.svg?logo=android\"></a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm7.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv7-45bf55.svg?logo=android\"></a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-x86_64.apk\"><img src=\"https://img.shields.io/badge/APK-x64-96ed89.svg?logo=android\"></a>\n        </td>\n        </tr>\n        <tr>\n            <td>Windows</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.Msix\"><img src=\"https://img.shields.io/badge/OfficialSetup-x64-0078d7.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.exe\"><img src=\"https://img.shields.io/badge/Setup-x64-2d7d9a.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Portable-x64.zip\"><img src=\"https://img.shields.io/badge/Portable-x64-67b7d1.svg?logo=windows\"></a>\n            </td>\n        </tr>\n        <tr>\n            <td>macOS</td>\n            <td>\n                <a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532\"><img src=\"https://img.shields.io/badge/IPA-ARM-D33A54.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS.dmg\"><img src=\"https://img.shields.io/badge/DMG-Universal-ea005e.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS-Installer.pkg\"><img src=\"https://img.shields.io/badge/PKG-Universal-bc544b.svg?logo=apple\" /></a>\n            </td>\n        </tr>\n        <tr>\n            <td>Linux</td>\n           <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Linux-x64.AppImage\"><img src=\"https://img.shields.io/badge/AppImage-x64-f84e29.svg?logo=linux\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Debian-x64.deb\"><img src=\"https://img.shields.io/badge/DebPackage-x64-FF9966.svg?logo=debian\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-rpm-x64.rpm\"><img src=\"https://img.shields.io/badge/RpmPackage-x64-F1B42F.svg?logo=redhat\"> </a>\n           </td>\n        </tr>\n    </tbody>\n</table>\n\n\n</div>\n\n## ⚙️ Instalação e tutoriais\n\n**Encontre informações de tutoriais em nossa página wiki clicando na imagem abaixo.**\n\n<div align=\"center\">\n\n[![Tutorials on Wiki](https://github.com/hiddify/hiddify-app/assets/125398461/95bb5cf8-c143-4934-87d6-b9d4c31e035e)](https://hiddify.com/app/)\n\n\n</div>\n\n## 🌎 Tradução\n\n\nMelhore os idiomas existentes ou adicione novos editando manualmente os arquivos JSON localizados em `/assets/translations` ou [![Translate with Inlang](https://img.shields.io/badge/%20-%20-3ECF8E?logo=i18next&logoColor=white)](https://fink.inlang.com/github.com/hiddify/hiddify-app) usando o [editor online Inlang](https://fink.inlang.com/editor/github.com/hiddify/hiddify-app).\n\n## ✏️ Agradecimentos\n\nGostaríamos de expressar nossa sincera gratidão aos contribuidores dos seguintes projetos, cuja base sólida e recursos inovadores têm melhorado significativamente o sucesso e a funcionalidade deste projeto.\n\n- [Sing-box](https://github.com/SagerNet/sing-box)\n- [Sing-box for Android](https://github.com/SagerNet/sing-box-for-android)\n- [Sing-box for Apple](https://github.com/SagerNet/sing-box-for-apple)\n- [Clash](https://github.com/Dreamacro/clash)\n- [Clash Meta](https://github.com/MetaCubeX/Clash.Meta)\n- [FClash](https://github.com/Fclash/Fclash)\n- [Vazirmatn Font by Saber Rastikerdar](https://github.com/rastikerdar/vazirmatn)\n- [Others](./pubspec.yaml)\n\n## 🎯 Doação e Suporte\n\nA maneira mais fácil de nos apoiar é clicar na estrela (⭐) no topo desta página.\n\n<div align=center>\n    \n<a href=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history?repo_id=643504282\" target=\"_blank\" style=\"display: block\" align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=dark\" width=\"721\" height=\"auto\">\n    <img alt=\"Star History of hiddify/hiddify-app\" src=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=light\" width=\"721\" height=\"auto\">\n  </picture>\n</a>\n\n</div>\n\nTambém precisamos de apoio financeiro para nossos serviços. Todas as nossas atividades são realizadas voluntariamente e o apoio financeiro será utilizado no desenvolvimento do projeto. Você pode ver nossos links de suporte [aqui](https://hiddify.com/donation-and-support/).\n\n## 👩‍🏫 Colaboração e Informações de Contato\n\nHiddify é um projeto impulsionado pela comunidade. Se você estiver interessado em contribuir, por favor, leia as [diretrizes de contribuição](./CONTRIBUTING.md). Agradeceríamos especialmente qualquer ajuda que pudermos obter nessas áreas: **Flutter, Go, desenvolvimento iOS (Swift), desenvolvimento Android (Kotlin).**\n\n<div align=center>\n\n<br>\n\n[![Email](https://img.shields.io/badge/Email-contribute@hiddify.com-005FF9?style=flat-square&logo=mail.ru)](mailto:contribute@hiddify.com)\n[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)\n[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)\n[![Twitter](https://img.shields.io/twitter/follow/hiddify_com?color=%231DA1F2&logo=twitter&logoColor=1DA1F2&style=flat-square)](https://twitter.com/intent/follow?screen_name=hiddify_com)\n\n</div>\n\n<p align=center>\nAgradecemos a todas as pessoas que estão participando deste projeto. Algumas pessoas aqui e muitas outras fora do Github. Isso significa muito para nós. ♥\n </p>\n \n<p align=center> \n<a href=\"https://github.com/hiddify/hiddify-app/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=hiddify/hiddify-next\" />\n</a>\n</p>\n<p align=center>\n Feito com <a rel=\"\" target=\"_blank\" href=\"https://contrib.rocks\">Contrib.Rocks</a> \n</p>\n"
  },
  {
    "path": "README_cn.md",
    "content": "<div dir=\"ltr\" align=center>\n\n[**![Lang_farsi](https://user-images.githubusercontent.com/125398461/234186932-52f1fa82-52c6-417f-8b37-08fe9250a55f.png) فارسی**](README_fa.md) / [**Русский 🇷🇺**](README_ru.md) / [**日本語 🇯🇵**](README_ja.md) / [**Portugês-BR 🇧🇷**](README_br.md) / [**English 🇺🇸**](README.md)\n</div>\n<br>\n\n<p align=\"center\"><img src=\"https://github.com/hiddify/hiddify.com/blob/main/docs/assets/hiddify-app-logo.svg\" width=56% /></p>\n<br>\n\n<div align=\"center\">\n\n[![GP-Intalls](https://img.shields.io/endpoint?color=green&logo=google-play&logoColor=green&url=https%3A%2F%2Fplay.cuzi.workers.dev%2Fplay%3Fi%3Dapp.hiddify.com%26l%3DGoogle%2520Play%26m%3D%24shortinstalls&style=flat-square)](https://play.google.com/store/apps/details?id=app.hiddify.com) [![Downloads](https://img.shields.io/github/downloads/hiddify/hiddify-next/total?style=flat-square&logo=github)](https://github.com/hiddify/hiddify-app/releases/)[![Last Version](https://img.shields.io/github/release/hiddify/hiddify-next/all.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![Last Release Date](https://img.shields.io/github/release-date/hiddify/hiddify-next.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![commits](https://img.shields.io/github/commit-activity/m/hiddify/hiddify-next?style=flat-square)](https://github.com/hiddify/hiddify-app/)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board/5)\n\n</div>\n\n\n\n\n## Hiddify app 是什么？\n\n<p dir=\"ltr\" style=\"font-size: 16px\">一款基于 <a href=\"https://github.com/SagerNet/sing-box\">Sing-box</a> 通用代理工具的跨平台代理客户端。Hiddify 提供了较全面的代理功能，例如自动选择节点、TUN 模式、使用远程配置文件等。Hiddify 无广告，并且代码开源。它为大家自由访问互联网提供了一个支持多种协议的、安全且私密的工具。</p>\n\n<div align=center>\n<img width=90% alt=\"English Demo\" src=\"https://github.com/hiddify/hiddify-app/assets/125398461/ffe5346d-3404-470f-b5e0-4364e23743d2\">\n</div>\n\n\n## 🚀 主要特性\n\n✈️ 多平台客户端：Android、iOS、Windows、macOS 和 Linux\n\n⭐ 简单易用的用户界面\n\n🔍 基于延迟自动选择节点\n\n🟡 全面的协议支持：**Vless、Vmess、Reality、TUIC、Wireguard、Hysteria、SSH**\n\n🟡 多种订阅链接和配置文件格式支持： **Sing-box、V2ray、Clash、Clash meta**\n\n🔄 支持自动更新订阅\n\n🔎 可显示包含了剩余天数和流量使用情况的配置文件信息\n\n🛡 开源、安全且由社区驱动\n\n🌙 深色和浅色模式\n\n⚙ 兼容所有的代理管理面板\n\n⭐ 适用于伊朗、中国、俄罗斯或其他国家的配置\n\n📱 官方商店有售\n\n## 🛍️ 在商店购买\n\n<a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532?platform=iphone\"><img height=50px src=\"https://github.com/user-attachments/assets/a7c62126-07ce-4f18-8197-bbb672f6d8be\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n<a href=\"https://play.google.com/store/apps/details?id=app.hiddify.com\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/blob/main/docs/google-play-badge.png\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n<a href=\"https://apps.microsoft.com/detail/Hiddify/9pdfnl3qv2s5?mode=mini\" target=\"_blank\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/assets/125398461/620750bb-4459-41b5-9f86-ba82119345b8\" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n\n\n## 📥 直接下载\n\n<div align=left>\n<table>\n    <thead align=left>\n        <tr>\n            <th>操作系统</th>\n            <th>下载链接</th>\n        </tr>\n    </thead>\n    <tbody align=left>\n        <tr>\n        <td>iOS</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-iOS.ipa\"><img src=\"https://img.shields.io/badge/IPA-Universal-c0c0c0.svg?logo=ios\"></a>\n            </td>\n        </tr>\n        <tr>\n        <td>Android</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-universal.apk\"><img src=\"https://img.shields.io/badge/APK-Universal-044d29.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm64.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv8-168039.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm7.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv7-45bf55.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-x86_64.apk\"><img src=\"https://img.shields.io/badge/APK-x64-96ed89.svg?logo=android\"></a>\n            </td>\n        </tr>\n        <tr>\n            <td>Windows</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.Msix\"><img src=\"https://img.shields.io/badge/OfficialSetup-x64-0078d7.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.exe\"><img src=\"https://img.shields.io/badge/Setup-x64-2d7d9a.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Portable-x64.zip\"><img src=\"https://img.shields.io/badge/Portable-x64-67b7d1.svg?logo=windows\"></a>\n            </td>\n        </tr>\n        <tr>\n            <td>macOS</td>\n            <td>\n                <a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532\"><img src=\"https://img.shields.io/badge/IPA-ARM-D33A54.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS.dmg\"><img src=\"https://img.shields.io/badge/DMG-Universal-ea005e.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS-Installer.pkg\"><img src=\"https://img.shields.io/badge/PKG-Universal-bc544b.svg?logo=apple\" /></a>\n            </td>\n        </tr>\n        <tr>\n            <td>Linux</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Linux-x64.AppImage\"><img src=\"https://img.shields.io/badge/AppImage-x64-f84e29.svg?logo=linux\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Debian-x64.deb\"><img src=\"https://img.shields.io/badge/DebPackage-x64-FF9966.svg?logo=debian\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-rpm-x64.rpm\"><img src=\"https://img.shields.io/badge/RpmPackage-x64-F1B42F.svg?logo=redhat\"> </a>\n            </td>\n        </tr>\n    </tbody>\n</table>\n\n\n\n</div>\n\n## ⚙️ 安装和教程\n**请单击下面的图片，在我们的维基页面上找到相关信息。**\n\n<div align=center>\n    \n[![Wiki上的所有教程](https://github.com/hiddify/hiddify-app/assets/125398461/95bb5cf8-c143-4934-87d6-b9d4c31e035e)](https://hiddify.com/app/)\n\n</div>\n \n\n## 🌎 翻译\n\n您可以通过手动编辑位于 `/assets/translations` 中的 JSON 文件，或使用 [Inlang 在线编辑器](https://fink.inlang.com/editor/github.com/hiddify/hiddify-app)来改进现有语言或添加新语言。\n\n## ✏️ 致谢\n我们谨向以下项目的贡献者表示诚挚的谢意，这些项目打下的坚实基础和开发的创新功能，显着增强了本项目的功能，为本项目的开发带来了成功。\n- [Sing-box](https://github.com/SagerNet/sing-box)\n- [Sing-box for Android](https://github.com/SagerNet/sing-box-for-android)\n- [Sing-box for Apple](https://github.com/SagerNet/sing-box-for-apple)\n- [Clash](https://github.com/Dreamacro/clash)\n- [Clash Meta](https://github.com/MetaCubeX/Clash.Meta)\n- [FClash](https://github.com/Fclash/Fclash)\n- [字体 Vazirmatn Font by Saber Rastikerdar](https://github.com/rastikerdar/vazirmatn)\n- [其他](./pubspec.yaml)\n\n\n\n## 🎯 捐赠和支持\n\n支持我们的最简单方法是单击此页面顶部的Star (⭐) 。\n\n<div align=center>\n\n<a href=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history?repo_id=643504282\" target=\"_blank\" style=\"display: block\" align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=dark\" width=\"721\" height=\"auto\">\n    <img alt=\"Star History of hiddify/hiddify-app\" src=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=light\" width=\"721\" height=\"auto\">\n  </picture>\n</a>\n\n</div>\n\n我们的服务也需要经济支持。我们所有的活动都是志愿性质的，经济支持将被用于项目的发展。您可以在 [这里](https://hiddify.com/donation-and-support/) 查看我们的支持地址。\n\n## 👩‍🏫 合作及联系信息\n\nHiddify 是一个由社区驱动的项目。如果您有兴趣为本项目做出贡献，请阅读 [贡献指南](./CONTRIBUTING.md)。我们将非常感谢您，如果您能够在以下领域提供任何帮助：Flutter、Go、iOS 开发 (Swift)、Android 开发 (Kotlin)。\n\n<div align=center>\n\n<br>\n\n[![Email](https://img.shields.io/badge/Email-contribute@hiddify.com-005FF9?style=flat-square&logo=mail.ru)](mailto:contribute@hiddify.com)\n[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)\n[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)\n[![Twitter](https://img.shields.io/twitter/follow/hiddify_com?color=%231DA1F2&logo=twitter&logoColor=1DA1F2&style=flat-square)](https://twitter.com/intent/follow?screen_name=hiddify_com)\n\n</div>\n\n<p align=center>\n我们非常感谢所有参与此项目的朋友，包括下面列出的这些朋友，以及许许多多没有在 Github 社区的朋友。这对我们来说意义重大。♥\n </p>\n\n\n<p align=center> \n<a href=\"https://github.com/hiddify/hiddify-app/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=hiddify/hiddify-next\" />\n</a>\n</p>\n<p align=center>\n 使用 <a rel=\"\" target=\"_blank\" href=\"https://contrib.rocks\">Contrib.Rocks</a> 制作\n</p>\n\n"
  },
  {
    "path": "README_fa.md",
    "content": "<div align=\"center\" markdown=\"1\" dir=\"ltr\">\n\n[**🇺🇸 English**](README.md) / [**🇨🇳 简体中文**](README_cn.md) / [**🇷🇺 Русский**](README_ru.md) / [**🇯🇵 日本語**](README_ja.md) / [**🇧🇷 Portugês-BR**](README_br.md)\n\n</div>\n<br>\n\n<p align=\"center\"><img src=\"https://github.com/hiddify/hiddify.com/blob/main/docs/assets/hiddify-app-logo.svg\" width=56% /></p>\n<br>\n\n<div align=\"center\">\n    \n[![GP-Intalls](https://img.shields.io/endpoint?color=green&logo=google-play&logoColor=green&url=https%3A%2F%2Fplay.cuzi.workers.dev%2Fplay%3Fi%3Dapp.hiddify.com%26l%3DGoogle%2520Play%26m%3D%24shortinstalls&style=flat-square)](https://play.google.com/store/apps/details?id=app.hiddify.com) [![Downloads](https://img.shields.io/github/downloads/hiddify/hiddify-next/total?style=flat-square&logo=github)](https://github.com/hiddify/hiddify-app/releases/)[![Last Version](https://img.shields.io/github/release/hiddify/hiddify-next/all.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![Last Release Date](https://img.shields.io/github/release-date/hiddify/hiddify-next.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![commits](https://img.shields.io/github/commit-activity/m/hiddify/hiddify-next?style=flat-square)](https://github.com/hiddify/hiddify-app/)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board/5)\n\n</div>\n\n## اپ هیدیفای چیست؟\n\nیک کلاینت خودکار مالتی‌پلتفرم مبتنی بر [سینگ‌باکس](https://github.com/SagerNet/sing-box) که به عنوان یک ابزار عمومی برای پروکسی عمل می‌کند. این برنامه طیف گسترده‌ای از قابلیت‌ها را ارائه می‌دهد مثل انتخاب خودکار نود، مود تونل، پروفایل‌های ریموت و غیره. این برنامه رایگان، بدون آگهی و منبع باز است. با پشتیبانی از طیف وسیعی از پروتکل‌ها، این اپلیکیشن یک ابزار امن و مطمئن برای دسترسی به اینترنت رایگان فراهم می‌کند.\n\n\n\n\n<div align=center>\n<img width=90% alt=\"Farsi Demo\" src=\"https://github.com/hiddify/hiddify-app/assets/125398461/cfdc4b0e-0a26-42f5-90ef-1d8587d2afd2\">\n\n</div>\n\n\n\n## 🚀 امکانات اصلی\n\n✈️ پشتیبانی از چند پلتفرم: اندروید، iOS، ویندوز، مک و لینوکس\n\n⭐ استفاده بسیار آسان با رابط کاربری ساده\n\n🔍 انتخاب خودکار بهترین سرور و کانفیگ بر اساس تاخیر\n\n🟡 پشتیبانی از رنج وسیعی از پروتکل‌ها\nVless, Vmess, Reality, TUIC, Hysteria, Wireguard, SSH, etc.\n\n🟡 پشتیبانی لینک‌های سابسکریپشن‌ مختلف:\nسینگ‌باکس، V2ray، کلش، کلش‌متا\n\n🔄 آپدیت خودکار لینک سابسکریپشن و کانفیگ‌ها\n\n🔎 نمایش اطلاعات پروفایل کاربر شامل روز و حجم باقیمانده\n\n🛡 اپن سورس، کاملا امن و کامیونیتی محور\n\n🌙 دارای تم دارک و لایت\n\n⚙ سازگار با تمام پنل‌ها\n\n⭐ کانفیگ متناسب برای ایران، چین، روسیه و‌ سایر کشورها\n\n📱 انتشار در استورهای معتبر\n\n\n\n## 🛍️ دریافت از استورها\n<div dir=rtl align=right>\n    \n<a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532?platform=iphone\"><img height=50px src=\"https://github.com/user-attachments/assets/a7c62126-07ce-4f18-8197-bbb672f6d8be\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n<a href=\"https://play.google.com/store/apps/details?id=app.hiddify.com\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/blob/main/docs/google-play-badge.png\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n<a href=\"https://apps.microsoft.com/detail/Hiddify/9pdfnl3qv2s5?mode=mini\" target=\"_blank\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/assets/125398461/620750bb-4459-41b5-9f86-ba82119345b8\" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n\n</div>\n\n## 📥 دانلود مستقیم\n<div dir=rtl align=right>\n\n   <table>\n    <thead align=right>\n        <tr>\n            <th>سیستم عامل</th>\n            <th>دانلود</th>\n        </tr>\n    </thead>\n    <tbody align=right>\n        <tr>\n        <td>iOS</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-iOS.ipa\"><img src=\"https://img.shields.io/badge/IPA-Universal-c0c0c0.svg?logo=ios\"></a>\n            </td>\n        </tr>\n        <tr>\n        <td>اندروید</td><td>\n             <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-universal.apk\"><img src=\"https://img.shields.io/badge/APK-Universal-044d29.svg?logo=android\"></a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm64.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv8-168039.svg?logo=android\"></a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm7.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv7-45bf55.svg?logo=android\"></a><br>\n            <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-x86_64.apk\"><img src=\"https://img.shields.io/badge/APK-x64-96ed89.svg?logo=android\"></a>\n        </td>\n        </tr>\n        <tr>\n            <td>ویندوز</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.Msix\"><img src=\"https://img.shields.io/badge/OfficialSetup-x64-0078d7.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.exe\"><img src=\"https://img.shields.io/badge/Setup-x64-2d7d9a.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Portable-x64.zip\"><img src=\"https://img.shields.io/badge/Portable-x64-67b7d1.svg?logo=windows\"></a>\n        </td>\n        </tr>\n        <tr>\n            <td>مک</td>\n            <td>\n                <a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532\"><img src=\"https://img.shields.io/badge/IPA-ARM-D33A54.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS.dmg\"><img src=\"https://img.shields.io/badge/DMG-Universal-ea005e.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS-Installer.pkg\"><img src=\"https://img.shields.io/badge/PKG-Universal-bc544b.svg?logo=apple\" /></a>\n            </td>\n       </tr>\n        <tr>\n            <td>لینوکس</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Linux-x64.AppImage\"><img src=\"https://img.shields.io/badge/AppImage-x64-f84e29.svg?logo=linux\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Debian-x64.deb\"><img src=\"https://img.shields.io/badge/DebPackage-x64-FF9966.svg?logo=debian\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-rpm-x64.rpm\"><img src=\"https://img.shields.io/badge/RpmPackage-x64-F1B42F.svg?logo=redhat\"> </a>\n            </td>\n        </tr>\n    </tbody>\n</table>\n\n## ⚙️ نصب و آموزش\n**برای مطالعه و مشاهده همه مطالب آموزشی در مورد این برنامه، با کلیک روی تصویر زیر به صفحه ویکی پروژه مراجعه کنید.**\n\n<div align=\"center\">\n\n[![همه آموزش‌ها در ویکی](https://github.com/hiddify/hiddify-app/assets/125398461/3b9ec2fe-9057-45fc-b19f-a1356e94525f)](https://hiddify.com/fa/app/)\n\n</div>\n\n\n\n## 🌎 ترجمه‌ها\n\n\nبا ویرایش دستی فایل‌های JSON در assets/translations/ یا با استفاده از [![Translate with Inlang](https://img.shields.io/badge/%20-%20-3ECF8E?logo=i18next&logoColor=white)](https://fink.inlang.com/github.com/hiddify/hiddify-app) [ویرایشگر آنلاین Inlang](https://fink.inlang.com/editor/github.com/hiddify/hiddify-app)، زبان‌های موجود را بهبود بدهید و یا زبان‌های جدید اضافه کنید.\n\n## ✏️ سپاسگزاری‌ها\nمایلیم از دست‌اندرکاران پروژه‌های زیر صمیمانه قدردانی کنیم که پایه قوی و ویژگی‌های نوآورانه آنها موفقیت و عملکرد این پروژه را به میزان قابل توجهی افزایش داده است.\n\n- [سینگ‌باکس](https://github.com/SagerNet/sing-box)\n- [سینگ‌باکس برای اندروید](https://github.com/SagerNet/sing-box-for-android)\n- [کلش](https://github.com/Dreamacro/clash)\n- [کلش‌متا](https://github.com/MetaCubeX/Clash.Meta)\n- [اف‌کلش](https://github.com/Fclash/Fclash)\n- [فونت وزیرمتن صابر راستی‌کردار](https://github.com/rastikerdar/vazirmatn)\n- [سایر](./pubspec.yaml)\n\n\n## 🎯 حمایت از پروژه\n\nساده‌ترین راه حمایت از ما کلیک کردن روی ستاره (⭐) بالای همین صفحه است.\n\n<div align=center>\n    \n<a href=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history?repo_id=643504282\" target=\"_blank\" style=\"display: block\" align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=dark\" width=\"721\" height=\"auto\">\n    <img alt=\"Star History of hiddify/hiddify-app\" src=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=light\" width=\"721\" height=\"auto\">\n  </picture>\n</a>\n\n</div>\n\nما برای سرویس هایمان به کمک مالی هم نیاز داریم. تمامی فعالیت‌های ما به صورت داوطلبانه انجام می‌شود و حمایت‌های مالی صرف توسعه پروژه می‌شود. اطلاعات و آدرس‌های حمایت‌ از ما را در [این لینک](https://hiddify.com/fa/donation-and-support/) مشاهده فرمایید.\n\n## 👩‍🏫 راه‌های همکاری و ارتباط با ما\n\nهیدیفای‌نکست یه پروژه کامیونیتی محور است. اگر به مشارکت در این پروژه علاقه دارید، لطفا راهنمای مشارکت در این پروژه را مطالعه فرمایید. ما به صورت ویژه هر گونه کمکی در این زمینه‌ها را ارج می‌نهیم: **فلاتر، Go، توسعه iOS (سوئیفت)، توسعه اندروید (کاتلین)**.\n\n\n\n<br>\n<div align=center>\n    \n[![Email](https://img.shields.io/badge/Email-contribute@hiddify.com-005FF9?style=flat-square&logo=mail.ru)](mailto:contribute@hiddify.com)\n[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)\n[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)\n[![Twitter](https://img.shields.io/twitter/follow/hiddify_com?color=%231DA1F2&logo=twitter&logoColor=1DA1F2&style=flat-square)](https://twitter.com/intent/follow?screen_name=hiddify_com)\n\n </div>\n \n<p align=center>\n از همه کسانی که در این پروژه مشارکت می‌کنند سپاسگزاریم. بعضی از آن‌ها اینجا هستند و خیلی های دیگه خارج از گیتهاب. همگی خیلی برای ما ارزشمندند. ♥\n </p>\n \n<p align=center> \n<a href=\"https://github.com/hiddify/hiddify-app/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=hiddify/hiddify-next\" />\n</a>\n</p>\n<p align=center>\n ساخته شده با <a rel=\"\" target=\"_blank\" href=\"https://contrib.rocks\">Contrib.Rocks</a> \n</p>\n"
  },
  {
    "path": "README_ja.md",
    "content": "<div dir=\"ltr\" align=center>\n\n[**![Lang_farsi](https://user-images.githubusercontent.com/125398461/234186932-52f1fa82-52c6-417f-8b37-08fe9250a55f.png) فارسی**](README_fa.md) / [**Русский 🇷🇺**](README_ru.md) / [**简体中文 🇨🇳**](README_cn.md) / [**English 🇺🇸**](README.md) / [**Portugês-BR 🇧🇷**](README_br.md)\n\n\n</div>\n<br>\n\n<p align=\"center\"><img src=\"https://github.com/hiddify/hiddify.com/blob/main/docs/assets/hiddify-app-logo.svg\" width=56% /></p>\n<br>\n\n<div align=\"center\">\n\n<!--\n![Hiddify logo + text](https://github.com/hiddify/hiddify-app/assets/125398461/d821cfe0-b4c4-441f-be4e-eb9209f59542)\n    -->\n\n[![GP-Intalls](https://img.shields.io/endpoint?color=green&logo=google-play&logoColor=green&url=https%3A%2F%2Fplay.cuzi.workers.dev%2Fplay%3Fi%3Dapp.hiddify.com%26l%3DGoogle%2520Play%26m%3D%24shortinstalls&style=flat-square)](https://play.google.com/store/apps/details?id=app.hiddify.com) [![Downloads](https://img.shields.io/github/downloads/hiddify/hiddify-next/total?style=flat-square&logo=github)](https://github.com/hiddify/hiddify-app/releases/)[![Last Version](https://img.shields.io/github/release/hiddify/hiddify-next/all.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![Last Release Date](https://img.shields.io/github/release-date/hiddify/hiddify-next.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![commits](https://img.shields.io/github/commit-activity/m/hiddify/hiddify-next?style=flat-square)](https://github.com/hiddify/hiddify-app/)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board/5)\n\n</div>\n\n\n\n\n## Hiddify app とは？\n\n<p dir=\"ltr\" style=\"font-size: 16px\"><a href=\"https://github.com/SagerNet/sing-box\">Sing-box</a> ユニバーサルプロキシツールチェーンに基づくマルチプラットフォームプロキシクライアントです。Hiddify は、自動ノード選択、TUN モード、リモートプロファイルなど、幅広い機能を提供します。Hiddify は無料でオープンソースです。幅広いプロトコルをサポートし、無料インターネットにアクセスするための安全でプライベートな方法を提供します。</p>\n\n<div align=center>\n<img width=90% alt=\"English Demo\" src=\"https://github.com/hiddify/hiddify-app/assets/125398461/ffe5346d-3404-470f-b5e0-4364e23743d2\">\n\n</div>\n\n## 🚀 主な特徴\n\n✈️ マルチプラットフォーム: Android、iOS、Windows、macOS 及び Linux\n\n⭐ 直感的でアクセシブルな UI\n\n🔍 遅延に基づいたノード選択\n\n🟡 幅広いプロトコル:\nVless、Vmess、Reality、TUIC、Hysteria、Wireguard、SSH など。\n\n🟡 サブスクリプションのリンクと設定フォーマット\n\n🔄 サブスクリプションの自動更新\n\n🔎 残り日数やトラフィック使用量などのプロフィール情報を表示\n\n🛡 オープンソース、セキュア、そしてコミュニティドリブン\n\n🌙 ダークモードとライトモード\n\n⚙ 全てのプロキシ管理パネルに対応\n\n⭐ イラン、中国、ロシア、その他の国に適した構成\n\n📱公式ストアで購入可能\n\n## 🛍️ 店舗で入手\n\n<a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532?platform=iphone\"><img height=50px src=\"https://github.com/user-attachments/assets/a7c62126-07ce-4f18-8197-bbb672f6d8be\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n<a href=\"https://play.google.com/store/apps/details?id=app.hiddify.com\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/blob/main/docs/google-play-badge.png\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n<a href=\"https://apps.microsoft.com/detail/Hiddify/9pdfnl3qv2s5?mode=mini\" target=\"_blank\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/assets/125398461/620750bb-4459-41b5-9f86-ba82119345b8\" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n\n\n## 📥 直接ダウンロード\n\n<div align=left>\n<table>\n    <thead align=left>\n        <tr>\n            <th>OS</th>\n            <th>ダウンロード</th>\n        </tr>\n    </thead>\n    <tbody align=left>\n        <tr>\n            <td>iOS</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-iOS.ipa\"><img src=\"https://img.shields.io/badge/IPA-Universal-c0c0c0.svg?logo=ios\"></a>\n            </td>\n        </tr>\n        <tr>\n        <td>Android</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-universal.apk\"><img src=\"https://img.shields.io/badge/APK-Universal-044d29.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm64.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv8-168039.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm7.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv7-45bf55.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-x86_64.apk\"><img src=\"https://img.shields.io/badge/APK-x64-96ed89.svg?logo=android\"></a>\n            </td>\n        </tr>\n        <tr>\n            <td>Windows</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.Msix\"><img src=\"https://img.shields.io/badge/OfficialSetup-x64-0078d7.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.exe\"><img src=\"https://img.shields.io/badge/Setup-x64-2d7d9a.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Portable-x64.zip\"><img src=\"https://img.shields.io/badge/Portable-x64-67b7d1.svg?logo=windows\"></a>\n            </td>\n        </tr>\n        <tr>\n            <td>macOS</td>\n            <td>\n                <a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532\"><img src=\"https://img.shields.io/badge/IPA-ARM-D33A54.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS.dmg\"><img src=\"https://img.shields.io/badge/DMG-Universal-ea005e.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS-Installer.pkg\"><img src=\"https://img.shields.io/badge/PKG-Universal-bc544b.svg?logo=apple\" /></a>\n            </td>\n        </tr>\n        <tr>\n            <td>Linux</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Linux-x64.AppImage\"><img src=\"https://img.shields.io/badge/AppImage-x64-f84e29.svg?logo=linux\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Debian-x64.deb\"><img src=\"https://img.shields.io/badge/DebPackage-x64-FF9966.svg?logo=debian\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-rpm-x64.rpm\"><img src=\"https://img.shields.io/badge/RpmPackage-x64-F1B42F.svg?logo=redhat\"> </a>\n            </td>\n        </tr>\n    </tbody>\n</table>\n\n\n</div>\n\n## ⚙️ インストールとチュートリアル\n\n**チュートリアル情報は、下の画像をクリックしてウィキのページをご覧ください。**\n\n<div align=\"center\">\n\n[![Tutorials on Wiki](https://github.com/hiddify/hiddify-app/assets/125398461/95bb5cf8-c143-4934-87d6-b9d4c31e035e)](https://hiddify.com/app/)\n\n\n</div>\n\n## 🌎 翻訳\n\nインストールとチュートリアル `/assets/translations` にある JSON ファイルを手動で編集するか、[Inlang オンラインエディタ](https://fink.inlang.com/editor/github.com/hiddify/hiddify-app)を使って、既存の言語を改良したり、新しい言語を追加したりすることができます。\n\n## ✏️ 謝辞\n\n堅牢な基盤と革新的な機能により、このプロジェクトの成功と機能性を大幅に向上させた、以下のプロジェクトのコントリビューターに心から感謝の意を表します。\n\n- [Sing-box](https://github.com/SagerNet/sing-box)\n- [Sing-box for Android](https://github.com/SagerNet/sing-box-for-android)\n- [Sing-box for Apple](https://github.com/SagerNet/sing-box-for-apple)\n- [Clash](https://github.com/Dreamacro/clash)\n- [Clash Meta](https://github.com/MetaCubeX/Clash.Meta)\n- [FClash](https://github.com/Fclash/Fclash)\n- [Saber Rastikerdar による Vazirmatn フォント](https://github.com/rastikerdar/vazirmatn)\n- [その他](./pubspec.yaml)\n\n## 🎯 寄付とサポート\n\n最も簡単な支援方法は、このページの上部にある star（⭐）をクリックすることです。\n\n<div align=center>\n\n<a href=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history?repo_id=643504282\" target=\"_blank\" style=\"display: block\" align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=dark\" width=\"721\" height=\"auto\">\n    <img alt=\"Star History of hiddify/hiddify-app\" src=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=light\" width=\"721\" height=\"auto\">\n  </picture>\n</a>\n\n</div>\n\nまた、私たちのサービスには財政的な支援も必要です。私たちの活動はすべて自発的に行われており、経済的支援はプロジェクトの発展に費やされます。私たちのサポートアドレスは[こちら](https://hiddify.com/donation-and-support/)からご覧いただけます。\n\n## 👩‍🏫 コラボレーションおよび連絡先\n\nHiddify はコミュニティドリブンのプロジェクトです。コントリビュートすることに興味がある方は、[コントリビューションガイドライン](./CONTRIBUTING.md)をお読みください。私たちは特に以下の分野において、どのような協力でもいただけるとありがたいです: **Flutter、Go、iOS開発（Swift）、Androi d開発（Kotlin）。**\n\n<div align=center>\n\n<br>\n\n[![Email](https://img.shields.io/badge/Email-contribute@hiddify.com-005FF9?style=flat-square&logo=mail.ru)](mailto:contribute@hiddify.com)\n[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)\n[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)\n[![Twitter](https://img.shields.io/twitter/follow/hiddify_com?color=%231DA1F2&logo=twitter&logoColor=1DA1F2&style=flat-square)](https://twitter.com/intent/follow?screen_name=hiddify_com)\n\n</div>\n\n<p align=center>\n このプロジェクトに参加してくれているすべての人に感謝しております。ここにいる人たちもいるし、GitHub の外にもたくさんいます。それは私たちにとって大きな意味があります。 ♥\n </p>\n\n<p align=center>\n<a href=\"https://github.com/hiddify/hiddify-app/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=hiddify/hiddify-next\" />\n</a>\n</p>\n<p align=center>\n <a rel=\"\" target=\"_blank\" href=\"https://contrib.rocks\">Contrib.Rocks</a> で作成。\n</p>\n"
  },
  {
    "path": "README_ru.md",
    "content": "\n<div dir=rtl align=center>\n    \n[**![Lang_farsi](https://user-images.githubusercontent.com/125398461/234186932-52f1fa82-52c6-417f-8b37-08fe9250a55f.png) فارسی**](README_fa.md) / [**简体中文 🇨🇳**](README_cn.md) / [**English 🇺🇸**](README.md) / [**日本語 🇯🇵**](README_ja.md) / [**Portugês-BR 🇧🇷**](README_br.md)\n\n</div>\n<br>\n\n<p align=\"center\"><img src=\"https://github.com/hiddify/hiddify.com/blob/main/docs/assets/hiddify-app-logo.svg\" width=56% /></p>\n<br>\n\n<div align=\"center\">\n    \n[![GP-Intalls](https://img.shields.io/endpoint?color=green&logo=google-play&logoColor=green&url=https%3A%2F%2Fplay.cuzi.workers.dev%2Fplay%3Fi%3Dapp.hiddify.com%26l%3DGoogle%2520Play%26m%3D%24shortinstalls&style=flat-square)](https://play.google.com/store/apps/details?id=app.hiddify.com) [![Downloads](https://img.shields.io/github/downloads/hiddify/hiddify-next/total?style=flat-square&logo=github)](https://github.com/hiddify/hiddify-app/releases/)[![Last Version](https://img.shields.io/github/release/hiddify/hiddify-next/all.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![Last Release Date](https://img.shields.io/github/release-date/hiddify/hiddify-next.svg?style=flat-square)](https://github.com/hiddify/hiddify-app/releases/)[![commits](https://img.shields.io/github/commit-activity/m/hiddify/hiddify-next?style=flat-square)](https://github.com/hiddify/hiddify-app/)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)[![Telegram Channel](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)[![Telegram Group](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board/5)\n\n</div>\n\n## Что такое Hiddify app?\nКроссплатформенный прокси-клиент на основе ядра [Sing-box](https://github.com/SagerNet/sing-box). Hiddify предлагает широкий спектр возможностей, таких как автоматический выбор узла, режим TUN, удалённые конфигурации (подписки). Приложение с открытым исходным кодом, без рекламы. Поддерживая широкий спектр протоколов, мы обеспечиваем безопасный и конфиденциальный доступ к свободному интернету.\n\n<div align=center>\n<img width=90% alt=\"English Demo\" src=\"https://github.com/hiddify/hiddify-app/assets/125398461/1b592bf9-b19f-4592-b02d-a3fa6216d257\">\n</div>\n\n## 🚀 Основные особенности\n⭐ Простотой и лаконичный интерфейс\n\n✈️ Кроссплатформенность: Android, Windows, Linux и macOS\n\n🔍 Автоматический выбор профиля с наименьшей задержкой\n\n🟡 Широкий выбор протоколов: Vless, Vmess, Reality, TUIC, Hysteria, Wireguard, SSH и прочие\n\n🟡 Поддержка всех основных форматов подписки: Sing-box, V2ray, Clash, Clash meta\n\n🔄 Автоматическое обновление подписки\n\n🔎 Отображение информации профиля, включая оставшиеся дни и использованный трафик.\n\n🛡 Открытый исходный код, безопасность, разрабатывается сообществом людей\n\n🌙 Темная и светлая темы\n\n⚙ Совместимость со всеми панелями управления прокси.\n\n⭐ Подходящая конфигурация для Ирана, Китая, России и других стран.\n\n📱Доступно в официальных магазинах.\n\n## 🛍️ Приобретите в магазинах\n\n<a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532?platform=iphone\"><img height=50px src=\"https://github.com/user-attachments/assets/a7c62126-07ce-4f18-8197-bbb672f6d8be\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n<a href=\"https://play.google.com/store/apps/details?id=app.hiddify.com\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/blob/main/docs/google-play-badge.png\"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n<a href=\"https://apps.microsoft.com/detail/Hiddify/9pdfnl3qv2s5?mode=mini\" target=\"_blank\"><img height=50px src=\"https://github.com/hiddify/hiddify-next/assets/125398461/620750bb-4459-41b5-9f86-ba82119345b8\" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n\n\n## 📥 Прямая загрузка\n<div align=left>\n<table>\n    <thead align=left>\n        <tr>\n            <th>Операционная система</th>\n            <th>Скачать</th>\n        </tr>\n    </thead>\n    <tbody align=left>\n        <tr>\n        <td>iOS</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-iOS.ipa\"><img src=\"https://img.shields.io/badge/IPA-Universal-c0c0c0.svg?logo=ios\"></a>\n            </td>\n        </tr>\n        <tr>\n        <td>Android</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-universal.apk\"><img src=\"https://img.shields.io/badge/APK-Universal-044d29.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm64.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv8-168039.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-arm7.apk\"><img src=\"https://img.shields.io/badge/APK-ARMv7-45bf55.svg?logo=android\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Android-x86_64.apk\"><img src=\"https://img.shields.io/badge/APK-x64-96ed89.svg?logo=android\"></a>\n            </td>\n        </tr>\n        <tr>\n            <td>Windows</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.Msix\"><img src=\"https://img.shields.io/badge/OfficialSetup-x64-0078d7.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Setup-x64.exe\"><img src=\"https://img.shields.io/badge/Setup-x64-2d7d9a.svg?logo=windows\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Windows-Portable-x64.zip\"><img src=\"https://img.shields.io/badge/Portable-x64-67b7d1.svg?logo=windows\"></a>\n            </td>\n        </tr>\n        <tr>\n            <td>MacOS</td>\n             <td>\n                <a href=\"https://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532\"><img src=\"https://img.shields.io/badge/IPA-ARM-D33A54.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS.dmg\"><img src=\"https://img.shields.io/badge/DMG-Universal-ea005e.svg?logo=apple\"></a><br>\n                <a href=\"https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-MacOS-Installer.pkg\"><img src=\"https://img.shields.io/badge/PKG-Universal-bc544b.svg?logo=apple\" /></a>\n            </td>\n        </tr>\n        <tr>\n            <td>Linux</td>\n            <td>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Linux-x64.AppImage\"><img src=\"https://img.shields.io/badge/AppImage-x64-f84e29.svg?logo=linux\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-Debian-x64.deb\"><img src=\"https://img.shields.io/badge/DebPackage-x64-FF9966.svg?logo=debian\"> </a><br>\n                <a href=\"https://github.com/hiddify/hiddify-app/releases/latest/download/Hiddify-rpm-x64.rpm\"><img src=\"https://img.shields.io/badge/RpmPackage-x64-F1B42F.svg?logo=redhat\"> </a>\n            </td>\n        </tr>\n    </tbody>\n</table>\n\n## ⚙️ Установка и руководства\n\n**Соответствующую информацию можно найти на нашей вики-странице, нажав на изображение ниже.**\n\n<div align=\"center\" width=\"100%\">\n \n[![Все уроки на Wiki](https://github.com/hiddify/hiddify-app/assets/125398461/708a4fdf-fcef-4b22-acc6-67e630687f0a)](https://hiddify.com/app/)\n\n</div>\n\n## 🌎 Переводы\n\nУлучшайте существующие языки или добавляйте новые, вручную редактируя JSON-файлы, расположенные в `/assets/translations`, или используя [Онлайн редактор Inlang](https://fink.inlang.com/editor/github.com/hiddify/hiddify-app)\n\n\n## ✏️ Благодарности\nМы хотели бы выразить нашу искреннюю признательность участникам следующих проектов, чья прочная основа и инновационные функции значительно повысили успех и функциональность этого проекта.\n\n- [Sing-box](https://github.com/SagerNet/sing-box)\n- [Sing-box для Android](https://github.com/SagerNet/sing-box-for-android)\n- [Sing-box для Apple](https://github.com/SagerNet/sing-box-for-apple)\n- [Clash](https://github.com/Dreamacro/clash)\n- [Clash Meta](https://github.com/MetaCubeX/Clash.Meta)\n- [FClash](https://github.com/Fclash/Fclash)\n- [Шрифт Vazirmatn от Saber Rastikerdar](https://github.com/rastikerdar/vazirmatn)\n- [Others](./pubspec.yaml)\n\n\n## 🎯 Пожертвования и поддержка\nСамый простой способ поддержать нас — нажать на звездочку (⭐) вверху этой страницы.\n\n<div align=center>\n    \n<a href=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history?repo_id=643504282\" target=\"_blank\" style=\"display: block\" align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=dark\" width=\"721\" height=\"auto\">\n    <img alt=\"Star History of hiddify/hiddify-app\" src=\"https://next.ossinsight.io/widgets/official/analyze-repo-stars-history/thumbnail.png?repo_id=643504282&image_size=auto&color_scheme=light\" width=\"721\" height=\"auto\">\n  </picture>\n</a>\n\n</div>\n\n\nНам также нужна финансовая поддержка для наших сервисов. Вся наша деятельность осуществляется на добровольных началах, а финансовая поддержка будет направлена на развитие проекта. Вы можете просмотреть адреса нашей поддержки [здесь](https://hiddify.com/donation-and-support/).\n\n## 👩‍🏫 Сотрудничество и контактная информация\n\nHiddify - это проект, развиваемый сообществом. Если вас интересует возможность внести свой вклад, пожалуйста, ознакомьтесь с [руководством](./CONTRIBUTING.md).  Мы бы особенно оценили любую помощь в следующих областях: **Flutter, Go, iOS разработка (Swift), Android разработка (Kotlin).**\n\n\n<div align=center>\n\n<br>\n\n[![Email](https://img.shields.io/badge/Email-contribute@hiddify.com-005FF9?style=flat-square&logo=mail.ru)](mailto:contribute@hiddify.com)\n[![Telegram Канал](https://img.shields.io/endpoint?label=Channel&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify&color=blue)](https://telegram.dog/hiddify)\n[![Группа в Telegram](https://img.shields.io/endpoint?color=neon&label=Support%20Group&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fhiddify_board)](https://telegram.dog/hiddify_board)\n[![Youtube](https://img.shields.io/youtube/channel/views/UCxrmeMvVryNfB4XL35lXQNg?label=Youtube&style=flat-square&logo=youtube)](https://www.youtube.com/@hiddify)\n[![Twitter](https://img.shields.io/twitter/follow/hiddify_com?color=%231DA1F2&logo=twitter&logoColor=1DA1F2&style=flat-square)](https://twitter.com/intent/follow?screen_name=hiddify_com)\n\n</div>\n<p align=center>\nМы ценим всех людей, которые участвуют в этом проекте. Некоторые люди здесь и многие-многие другие за пределами Github. Это очень много значит для нас. ♥\n </p>\n \n<p align=center> \n<a href=\"https://github.com/hiddify/hiddify-app/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=hiddify/hiddify-next\" />\n</a>\n</p>\n<p align=center>\n Сделано с <a rel=\"\" target=\"_blank\" href=\"https://contrib.rocks\">Contrib.Rocks</a> \n</p>\n"
  },
  {
    "path": "analysis_options.yaml",
    "content": "include: package:lint/strict.yaml\n\nanalyzer:\n  plugins:\n    - custom_lint\n  exclude:\n    - \"hiddify-core/**\"\n    - \"**.g.dart\"\n    - \"lib/gen/**\"\n  errors:\n    invalid_annotation_target: ignore\n\nformatter:\n  page_width: 120\n\nlinter:\n  rules:\n    sort_pub_dependencies: false\n    sort_unnamed_constructors_first: false\n    avoid_classes_with_only_static_members: false\n\ncustom_lint:\n  rules:\n    # Enable one rule\n    - provider_parameters"
  },
  {
    "path": "android/.gitignore",
    "content": "gradle-wrapper.jar\n/.gradle\n/captures/\n/gradlew\n/gradlew.bat\n/local.properties\nGeneratedPluginRegistrant.java\n\n# Remember to never publicly share your keystore.\n# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app\nkey.properties\n**/*.keystore\n**/*.jks\n\n/app/libs/*\n!/app/libs/.gitkeep\n\n/app/.cxx"
  },
  {
    "path": "android/.stignore",
    "content": "gradle-wrapper.jar\n.gradle\ncaptures/\ngradlew\ngradlew.bat\nlocal.properties\nGeneratedPluginRegistrant.java\n\nkey.properties\n**.keystore\n**.jks"
  },
  {
    "path": "android/app/build.gradle",
    "content": "\nplugins { \n    id \"com.android.application\" \n    id \"org.jetbrains.kotlin.android\" \n    id \"dev.flutter.flutter-gradle-plugin\" \n    id \"com.google.protobuf\" version \"0.9.4\" \n    id \"com.squareup.wire\" version \"5.3.1\"\n}\n\nwire {\n    kotlin {\n        android = true\n    }\n    protoPath {\n        srcDir 'src/main/protos'\n    }\n    sourcePath {\n        srcDir 'src/main/protos/'\n        include '**'\n    }\n}\n\n\ndef localProperties = new Properties()\ndef localPropertiesFile = rootProject.file('local.properties')\nif (localPropertiesFile.exists()) {\n    localPropertiesFile.withReader('UTF-8') { reader ->\n        localProperties.load(reader)\n    }\n}\n\nboolean hasKeyStore = false\n\ndef keystoreProperties = new Properties()\ndef keystorePropertiesFile = rootProject.file('key.properties')\nif (keystorePropertiesFile.exists()) {\n    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))\n    hasKeyStore = true\n} else {\n    println \"+++\"\n    println \"No keystore defined. The app will not be signed.\"\n    println \"Create a android/key.properties file with the following properties:\"\n    println \"storePassword\"\n    println \"keyPassword\"\n    println \"keyAlias\"\n    println \"storeFile\"\n    println \"+++\"\n}\n\ndef flutterVersionCode = localProperties.getProperty('flutter.versionCode')?: '1'\n\ndef flutterVersionName = localProperties.getProperty('flutter.versionName') ?: '1.0'\n\nandroid {\n    namespace 'com.hiddify.hiddify'\n    testNamespace \"test.com.hiddify.hiddify\"\n    compileSdkVersion 36\n    ndkVersion \"28.2.13676358\"\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_17\n        targetCompatibility JavaVersion.VERSION_17\n    }\n\n    kotlinOptions {\n        jvmTarget = '17'\n    }\n\n    sourceSets {\n        main.java.srcDirs += 'src/main/kotlin'\n    }\n\n    defaultConfig {\n        applicationId \"app.hiddify.com\"\n        minSdkVersion flutter.minSdkVersion\n        targetSdkVersion 36\n        versionCode flutterVersionCode.toInteger()\n        versionName flutterVersionName\n        multiDexEnabled true\n    }\n\n    splits {\n        abi {\n            enable true\n            reset()\n            //noinspection ChromeOsAbiSupport\n            include \"x86_64\", \"armeabi-v7a\", \"arm64-v8a\"\n\n            universalApk true\n        }\n    }\n\n    if (hasKeyStore) {\n        signingConfigs {\n            release {\n                keyAlias keystoreProperties['keyAlias']\n                keyPassword keystoreProperties['keyPassword']\n                storeFile file(keystoreProperties['storeFile'])\n                storePassword keystoreProperties['storePassword']\n            }\n        }\n    }\n\n    buildTypes {\n        release {\n            if (hasKeyStore) {\n                signingConfig signingConfigs.release\n            } else {\n                signingConfig signingConfigs.debug\n            }\n            ndk {\n                //noinspection ChromeOsAbiSupport\n                abiFilters \"x86_64\", \"armeabi-v7a\", \"arm64-v8a\"\n                debugSymbolLevel 'FULL'\n            }\n        }\n    }\n\n    buildFeatures {\n        viewBinding true\n        aidl true\n    }\n\n}\n\nandroid.applicationVariants.all { variant ->\n    variant.outputs.each { output ->\n        output.versionCodeOverride = android.defaultConfig.versionCode\n    }\n}\n\nflutter {\n    source '../..'\n}\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])\n\n    implementation 'com.google.code.gson:gson:2.11.0'\n    implementation 'androidx.core:core-ktx:1.16.0'\n    implementation 'androidx.appcompat:appcompat:1.7.0'\n    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.8.7'\n    implementation \"androidx.compose.ui:ui:1.7.8\"\n    implementation(\"com.squareup.wire:wire-grpc-client:5.3.1\")\n\n    implementation 'io.grpc:grpc-okhttp:1.64.0'\n    implementation 'io.grpc:grpc-protobuf-lite:1.64.0'\n    implementation 'io.grpc:grpc-stub:1.64.0'\n//    protoPath(project(':hiddify_api'))\n//    implementation project(':hiddify_api')\n\n\n\n\n}\n"
  },
  {
    "path": "android/app/libs/.gitkeep",
    "content": ""
  },
  {
    "path": "android/app/src/debug/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <!-- The INTERNET permission is required for development. Specifically,\n         the Flutter tool needs it to communicate with the running application\n         to allow setting breakpoints, to provide hot reload, etc.\n    -->\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n</manifest>\n"
  },
  {
    "path": "android/app/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <uses-feature\n        android:name=\"android.software.leanback\"\n        android:required=\"false\" />\n    <uses-feature\n        android:name=\"android.hardware.touchscreen\"\n        android:required=\"false\" />\n    <uses-feature\n        android:name=\"android.hardware.camera\"\n        android:required=\"false\" />\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" />\n    <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE_SPECIAL_USE\" />\n    <uses-permission android:name=\"android.permission.POST_NOTIFICATIONS\" />\n    <uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\" />\n    <uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\" />\n    <uses-permission android:name=\"android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS\" />\n    <uses-permission android:name=\"android.permission.CAMERA\" />\n\n    <uses-permission\n        android:name=\"android.permission.QUERY_ALL_PACKAGES\"\n        tools:ignore=\"QueryAllPackagesPermission\" />\n\n    <application\n        android:name=\".Application\"\n        android:banner=\"@mipmap/ic_banner\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"Hiddify\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:networkSecurityConfig=\"@xml/network_security_config\"\n        tools:targetApi=\"31\">\n\n        <meta-data\n            android:name=\"flutter_deeplinking_enabled\"\n            android:value=\"true\" />\n\n        <meta-data\n            android:name=\"android.app.shortcuts\"\n            android:resource=\"@xml/shortcuts\" />\n\n        <activity\n            android:name=\".MainActivity\"\n            android:configChanges=\"orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode\"\n            android:exported=\"true\"\n            android:hardwareAccelerated=\"true\"\n            android:launchMode=\"singleTop\"\n            android:theme=\"@style/LaunchTheme\"\n            android:windowSoftInputMode=\"adjustResize\">\n\n\n            <!-- Specifies an Android theme to apply to this Activity as soon as\n                 the Android process has started. This theme is visible to the user\n                 while the Flutter UI initializes. After that, this theme continues\n                 to determine the Window background behind the Flutter UI. -->\n            <meta-data\n                android:name=\"io.flutter.embedding.android.NormalTheme\"\n                android:resource=\"@style/NormalTheme\" />\n\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LEANBACK_LAUNCHER\" />\n\n            </intent-filter>\n            <intent-filter>\n                <action android:name=\"android.intent.action.VIEW\" />\n\n                <category android:name=\"android.intent.category.DEFAULT\" />\n                <category android:name=\"android.intent.category.BROWSABLE\" />\n\n                <data android:scheme=\"hiddify\" />\n                <data android:scheme=\"v2ray\" />\n                <data android:scheme=\"v2rayn\" />\n                <data android:scheme=\"v2rayng\" />\n                <data android:scheme=\"clash\" />\n                <data android:scheme=\"clashmeta\" />\n                <data android:scheme=\"sing-box\" />\n\n                <!-- <data android:host=\"import\" />\n                <data android:host=\"install-config\" />\n                <data android:host=\"import-remote-profile\" />\n                <data android:host=\"install-sub\" /> -->\n            </intent-filter>\n\n            <intent-filter>\n                <action android:name=\"android.service.quicksettings.action.QS_TILE_PREFERENCES\" />\n            </intent-filter>\n        </activity>\n\n        <activity\n            android:name=\".ShortcutActivity\"\n            android:excludeFromRecents=\"true\"\n            android:exported=\"true\"\n            android:label=\"@string/quick_toggle\"\n            android:launchMode=\"singleTask\"\n            android:taskAffinity=\"\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.CREATE_SHORTCUT\" />\n            </intent-filter>\n        </activity>\n\n        <service\n            android:name=\".bg.TileService\"\n            android:directBootAware=\"true\"\n            android:exported=\"true\"\n            android:icon=\"@drawable/ic_stat_logo\"\n            android:permission=\"android.permission.BIND_QUICK_SETTINGS_TILE\"\n            tools:targetApi=\"n\">\n            <intent-filter>\n                <action android:name=\"android.service.quicksettings.action.QS_TILE\" />\n            </intent-filter>\n            <meta-data\n                android:name=\"android.service.quicksettings.TOGGLEABLE_TILE\"\n                android:value=\"true\" />\n        </service>\n        <service\n            android:name=\".bg.VPNService\"\n            android:exported=\"false\"\n            android:foregroundServiceType=\"specialUse\"\n            android:permission=\"android.permission.BIND_VPN_SERVICE\">\n            <intent-filter>\n                <action android:name=\"android.net.VpnService\" />\n            </intent-filter>\n            <property\n                android:name=\"android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE\"\n                android:value=\"vpn\" />\n            <meta-data android:name=\"android.net.VpnService.SUPPORTS_ALWAYS_ON\"\n                android:value=\"true\"/>\n        </service>\n        <service\n            android:name=\".bg.ProxyService\"\n            android:exported=\"false\"\n            android:foregroundServiceType=\"specialUse\">\n            <property\n                android:name=\"android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE\"\n                android:value=\"proxy\" />\n        </service>\n        <!-- Don't delete the meta-data below.\n             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->\n        <meta-data\n            android:name=\"flutterEmbedding\"\n            android:value=\"2\" />\n    </application>\n</manifest>"
  },
  {
    "path": "android/app/src/main/aidl/com/hiddify/hiddify/IService.aidl",
    "content": "package com.hiddify.hiddify;\n\nimport com.hiddify.hiddify.IServiceCallback;\n\ninterface IService {\n  int getStatus();\n  void registerCallback(in IServiceCallback callback);\n  oneway void unregisterCallback(in IServiceCallback callback);\n}"
  },
  {
    "path": "android/app/src/main/aidl/com/hiddify/hiddify/IServiceCallback.aidl",
    "content": "package com.hiddify.hiddify;\n\ninterface IServiceCallback {\n  void onServiceStatusChanged(int status);\n  void onServiceAlert(int type, String message);\n  void onServiceWriteLog(String message);\n  void onServiceResetLogs(in List<String> messages);\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/ActiveGroupsChannel.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.util.Log\nimport com.google.gson.Gson\n//import com.hiddify.hiddify.utils.CommandClient\nimport com.hiddify.hiddify.utils.ParsedOutboundGroup\nimport io.flutter.embedding.engine.plugins.FlutterPlugin\nimport io.flutter.plugin.common.EventChannel\nimport com.hiddify.core.libbox.OutboundGroup\nimport kotlinx.coroutines.CoroutineScope\n\n//\n//class ActiveGroupsChannel(private val scope: CoroutineScope) : FlutterPlugin,\n//    CommandClient.Handler {\n//    companion object {\n//        const val TAG = \"A/ActiveGroupsChannel\"\n//        const val CHANNEL = \"com.hiddify.app/active-groups\"\n//        val gson = Gson()\n//    }\n//\n//    private val client =\n//        CommandClient(scope, CommandClient.ConnectionType.GroupOnly, this)\n//\n//    private var channel: EventChannel? = null\n//    private var event: EventChannel.EventSink? = null\n//\n//    override fun updateGroups(groups: List<OutboundGroup>) {\n//        MainActivity.instance.runOnUiThread {\n//            val parsedGroups = groups.map { group -> ParsedOutboundGroup.fromOutbound(group) }\n//            event?.success(gson.toJson(parsedGroups))\n//        }\n//    }\n//\n//    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {\n//        channel = EventChannel(\n//            flutterPluginBinding.binaryMessenger,\n//            CHANNEL\n//        )\n//\n//        channel!!.setStreamHandler(object : EventChannel.StreamHandler {\n//            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {\n//                event = events\n//                Log.d(TAG, \"connecting active groups command client\")\n//                client.connect()\n//            }\n//\n//            override fun onCancel(arguments: Any?) {\n//                event = null\n//                Log.d(TAG, \"disconnecting active groups command client\")\n//                client.disconnect()\n//            }\n//        })\n//    }\n//\n//    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {\n//        event = null\n//        client.disconnect()\n//        channel?.setStreamHandler(null)\n//    }\n//}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/Application.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.app.Application\nimport android.app.NotificationManager\nimport android.content.Context\nimport android.content.Intent\nimport android.content.IntentFilter\nimport android.net.ConnectivityManager\nimport android.net.wifi.WifiManager\nimport android.os.PowerManager\nimport androidx.core.content.getSystemService\nimport com.hiddify.hiddify.bg.AppChangeReceiver\nimport go.Seq\nimport com.hiddify.hiddify.Application as BoxApplication\n\nclass Application : Application() {\n\n    override fun attachBaseContext(base: Context?) {\n        super.attachBaseContext(base)\n        application = this\n    }\n\n    override fun onCreate() {\n        super.onCreate()\n\n        Seq.setContext(this)\n\n        registerReceiver(AppChangeReceiver(), IntentFilter().apply {\n            addAction(Intent.ACTION_PACKAGE_ADDED)\n            addDataScheme(\"package\")\n        })\n    }\n\n    companion object {\n        lateinit var application: BoxApplication\n        val notification by lazy { application.getSystemService<NotificationManager>()!! }\n        val connectivity by lazy { application.getSystemService<ConnectivityManager>()!! }\n        val packageManager by lazy { application.packageManager }\n        val powerManager by lazy { application.getSystemService<PowerManager>()!! }\n        val notificationManager by lazy { application.getSystemService<NotificationManager>()!! }\n\n        val wifiManager by lazy { application.getSystemService<WifiManager>()!! }\n\n    }\n\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/EventHandler.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.util.Log\nimport androidx.lifecycle.Observer\nimport com.hiddify.hiddify.constant.Alert\nimport com.hiddify.hiddify.constant.Status\nimport io.flutter.embedding.engine.plugins.FlutterPlugin\nimport io.flutter.plugin.common.EventChannel\nimport io.flutter.plugin.common.JSONMethodCodec\n\nclass EventHandler : FlutterPlugin {\n\n    companion object {\n        const val TAG = \"A/EventHandler\"\n        const val SERVICE_STATUS = \"com.hiddify.app/service.status\"\n        const val SERVICE_ALERTS = \"com.hiddify.app/service.alerts\"\n    }\n\n    private var statusChannel: EventChannel? = null\n    private var alertsChannel: EventChannel? = null\n\n    private var statusObserver: Observer<Status>? = null\n    private var alertsObserver: Observer<ServiceEvent?>? = null\n\n    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {\n        statusChannel = EventChannel(flutterPluginBinding.binaryMessenger, SERVICE_STATUS, JSONMethodCodec.INSTANCE)\n        alertsChannel = EventChannel(flutterPluginBinding.binaryMessenger, SERVICE_ALERTS, JSONMethodCodec.INSTANCE)\n\n        statusChannel!!.setStreamHandler(object : EventChannel.StreamHandler {\n            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {\n                statusObserver = Observer {\n                    Log.d(TAG, \"new status: $it\")\n                    val map = listOf(\n                        Pair(\"status\", it.name)\n                    )\n                        .toMap()\n                    events?.success(map)\n                }\n                MainActivity.instance.serviceStatus.observeForever(statusObserver!!)\n            }\n\n            override fun onCancel(arguments: Any?) {\n                if (statusObserver != null)\n                    MainActivity.instance.serviceStatus.removeObserver(statusObserver!!)\n            }\n        })\n\n        alertsChannel!!.setStreamHandler(object : EventChannel.StreamHandler {\n            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {\n                alertsObserver = Observer {\n                    if (it == null) return@Observer\n                    Log.d(TAG, \"new alert: $it\")\n                    val map = listOf(\n                        Pair(\"status\", it.status.name),\n                        Pair(\"alert\", it.alert?.name),\n                        Pair(\"message\", it.message)\n                    )\n                        .mapNotNull { p -> p.second?.let { Pair(p.first, p.second) } }\n                        .toMap()\n                    events?.success(map)\n                }\n                MainActivity.instance.serviceAlerts.observeForever(alertsObserver!!)\n            }\n\n            override fun onCancel(arguments: Any?) {\n                if (alertsObserver != null)\n                    MainActivity.instance.serviceAlerts.removeObserver(alertsObserver!!)\n            }\n        })\n    }\n\n    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {\n        if (statusObserver != null)\n            MainActivity.instance.serviceStatus.removeObserver(statusObserver!!)\n        statusChannel?.setStreamHandler(null)\n        if (alertsObserver != null)\n            MainActivity.instance.serviceAlerts.removeObserver(alertsObserver!!)\n        alertsChannel?.setStreamHandler(null)\n    }\n}\n\ndata class ServiceEvent(val status: Status, val alert: Alert? = null, val message: String? = null)"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/GroupsChannel.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.util.Log\nimport com.google.gson.Gson\n//import com.hiddify.hiddify.utils.CommandClient\nimport com.hiddify.hiddify.utils.ParsedOutboundGroup\nimport io.flutter.embedding.engine.plugins.FlutterPlugin\nimport io.flutter.plugin.common.EventChannel\nimport com.hiddify.core.libbox.OutboundGroup\nimport kotlinx.coroutines.CoroutineScope\n//\n//class GroupsChannel(private val scope: CoroutineScope) : FlutterPlugin, CommandClient.Handler {\n//    companion object {\n//        const val TAG = \"A/GroupsChannel\"\n//        const val CHANNEL = \"com.hiddify.app/groups\"\n//        val gson = Gson()\n//    }\n//\n//    private val client =\n//        CommandClient(scope, CommandClient.ConnectionType.Groups, this)\n//\n//    private var channel: EventChannel? = null\n//    private var event: EventChannel.EventSink? = null\n//\n//    override fun updateGroups(groups: List<OutboundGroup>) {\n//        MainActivity.instance.runOnUiThread {\n//            val parsedGroups = groups.map { group -> ParsedOutboundGroup.fromOutbound(group) }\n//            event?.success(gson.toJson(parsedGroups))\n//        }\n//    }\n//\n//    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {\n//        channel = EventChannel(\n//            flutterPluginBinding.binaryMessenger,\n//            CHANNEL\n//        )\n//\n//        channel!!.setStreamHandler(object : EventChannel.StreamHandler {\n//            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {\n//                event = events\n//                Log.d(TAG, \"connecting groups command client\")\n//                client.connect()\n//            }\n//\n//            override fun onCancel(arguments: Any?) {\n//                event = null\n//                Log.d(TAG, \"disconnecting groups command client\")\n//                client.disconnect()\n//            }\n//        })\n//    }\n//\n//    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {\n//        event = null\n//        client.disconnect()\n//        channel?.setStreamHandler(null)\n//    }\n//}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/LogHandler.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.util.Log\nimport io.flutter.embedding.engine.plugins.FlutterPlugin\nimport io.flutter.plugin.common.EventChannel\n\n\nclass LogHandler : FlutterPlugin {\n\n    companion object {\n        const val TAG = \"A/LogHandler\"\n        const val SERVICE_LOGS = \"com.hiddify.app/service.logs\"\n    }\n\n    private lateinit var logsChannel: EventChannel\n\n    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {\n        logsChannel = EventChannel(flutterPluginBinding.binaryMessenger, SERVICE_LOGS)\n\n        logsChannel.setStreamHandler(object : EventChannel.StreamHandler {\n            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {\n                val activity = MainActivity.instance\n                events?.success(activity.logList)\n                activity.logCallback = {\n                    events?.success(activity.logList)\n                }\n            }\n\n            override fun onCancel(arguments: Any?) {\n                MainActivity.instance.logCallback = null\n            }\n        })\n    }\n\n    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/MainActivity.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.annotation.SuppressLint\nimport android.content.Intent\nimport android.Manifest\nimport android.content.pm.PackageManager\nimport android.net.VpnService\nimport android.os.Build\nimport android.util.Log\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.core.app.ActivityCompat\nimport androidx.core.content.ContextCompat\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.lifecycleScope\nimport com.hiddify.hiddify.bg.ServiceConnection\nimport com.hiddify.hiddify.bg.ServiceNotification\nimport com.hiddify.hiddify.constant.Alert\nimport com.hiddify.hiddify.constant.ServiceMode\nimport com.hiddify.hiddify.constant.Status\nimport io.flutter.embedding.android.FlutterFragmentActivity\nimport io.flutter.embedding.engine.FlutterEngine\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport java.util.LinkedList\n\n\nclass MainActivity : FlutterFragmentActivity(), ServiceConnection.Callback {\n    companion object {\n        private const val TAG = \"ANDROID/MyActivity\"\n        lateinit var instance: MainActivity\n\n        const val VPN_PERMISSION_REQUEST_CODE = 1001\n        const val NOTIFICATION_PERMISSION_REQUEST_CODE = 1010\n    }\n\n    private val connection = ServiceConnection(this, this)\n\n    val logList = LinkedList<String>()\n    var logCallback: ((Boolean) -> Unit)? = null\n    val serviceStatus = MutableLiveData(Status.Stopped)\n    val serviceAlerts = MutableLiveData<ServiceEvent?>(null)\n\n    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {\n        super.configureFlutterEngine(flutterEngine)\n        instance = this\n        reconnect()\n        flutterEngine.plugins.add(MethodHandler(lifecycleScope))\n        flutterEngine.plugins.add(PlatformSettingsHandler())\n        flutterEngine.plugins.add(EventHandler())\n        flutterEngine.plugins.add(LogHandler())\n//        flutterEngine.plugins.add(GroupsChannel(lifecycleScope))\n//        flutterEngine.plugins.add(ActiveGroupsChannel(lifecycleScope))\n//        flutterEngine.plugins.add(StatsChannel(lifecycleScope))\n    }\n\n    fun reconnect() {\n        connection.reconnect()\n    }\n\n    @SuppressLint(\"NewApi\")\n    fun startService() {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !ServiceNotification.checkPermission()) {\n            notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)\n            return\n        }\n        startService0()\n    }\n\n    private fun startService0() {\n        lifecycleScope.launch(Dispatchers.IO) {\n            if (Settings.rebuildServiceMode()) {\n                connection.reconnect()\n            }\n            if (Settings.serviceMode == ServiceMode.VPN) {\n                if (prepare()) {\n                    return@launch\n                }\n            }\n            val intent = Intent(Application.application, Settings.serviceClass())\n            withContext(Dispatchers.Main) {\n                ContextCompat.startForegroundService(this@MainActivity, intent)\n            }\n            Settings.startedByUser = true\n        }\n    }\n\n    private suspend fun prepare() = withContext(Dispatchers.Main) {\n        try {\n            val intent = VpnService.prepare(this@MainActivity)\n            if (intent != null) {\n                prepareLauncher.launch(intent)\n                true\n            } else {\n                false\n            }\n        } catch (e: Exception) {\n            onServiceAlert(Alert.RequestVPNPermission, e.message)\n            true\n        }\n    }\n    private val notificationPermissionLauncher =\n        registerForActivityResult(\n            ActivityResultContracts.RequestPermission(),\n        ) { isGranted ->\n            if (Settings.dynamicNotification && !isGranted) {\n                onServiceAlert(Alert.RequestNotificationPermission, null)\n            } else {\n                startService0()\n            }\n        }\n\n    private val prepareLauncher =\n        registerForActivityResult(\n            ActivityResultContracts.StartActivityForResult(),\n        ) { result ->\n            if (result.resultCode == RESULT_OK) {\n                startService0()\n            } else {\n                onServiceAlert(Alert.RequestVPNPermission, null)\n            }\n        }\n\n    override fun onServiceStatusChanged(status: Status) {\n        serviceStatus.postValue(status)\n    }\n\n    override fun onServiceAlert(type: Alert, message: String?) {\n        serviceAlerts.postValue(ServiceEvent(Status.Stopped, type, message))\n    }\n\n\n\n\n    override fun onDestroy() {\n        connection.disconnect()\n        super.onDestroy()\n    }\n\n    @SuppressLint(\"NewApi\")\n    private fun grantNotificationPermission() {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {\n            ActivityCompat.requestPermissions(\n                this,\n                arrayOf(Manifest.permission.POST_NOTIFICATIONS),\n                NOTIFICATION_PERMISSION_REQUEST_CODE\n            )\n        }\n    }\n\n    override fun onRequestPermissionsResult(\n        requestCode: Int,\n        permissions: Array<out String>,\n        grantResults: IntArray\n    ) {\n        if (requestCode == NOTIFICATION_PERMISSION_REQUEST_CODE) {\n            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {\n                startService()\n            } else onServiceAlert(Alert.RequestNotificationPermission, null)\n        }\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n    }\n\n    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n        super.onActivityResult(requestCode, resultCode, data)\n        if (requestCode == VPN_PERMISSION_REQUEST_CODE) {\n            if (resultCode == RESULT_OK) startService()\n            else onServiceAlert(Alert.RequestVPNPermission, null)\n        } else if (requestCode == NOTIFICATION_PERMISSION_REQUEST_CODE) {\n            if (resultCode == RESULT_OK) startService()\n            else onServiceAlert(Alert.RequestNotificationPermission, null)\n        }\n    }\n}\n"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/MethodHandler.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.util.Log\nimport com.hiddify.hiddify.bg.BoxService\n//import com.hiddify.hiddify.bg.BoxService.Companion.workingDir\nimport com.hiddify.hiddify.constant.Status\nimport io.flutter.embedding.engine.plugins.FlutterPlugin\nimport io.flutter.plugin.common.MethodCall\nimport io.flutter.plugin.common.MethodChannel\n\nimport com.hiddify.core.libbox.Libbox\nimport com.hiddify.core.mobile.Mobile\nimport com.hiddify.core.mobile.SetupOptions\nimport com.hiddify.hiddify.bg.Bugs\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\nimport java.io.File\n\nclass MethodHandler(private val scope: CoroutineScope) : FlutterPlugin,\n    MethodChannel.MethodCallHandler {\n    private var channel: MethodChannel? = null\n\n    companion object {\n        const val TAG = \"A/MethodHandler\"\n        const val channelName = \"com.hiddify.app/method\"\n\n        enum class Trigger(val method: String) {\n            Setup(\"setup\"),\n            Start(\"start\"),\n            Stop(\"stop\"),\n            Restart(\"restart\"),\n            AddGrpcClientPublicKey(\"add_grpc_client_public_key\"),\n            GetGrpcServerPublicKey(\"get_grpc_server_public_key\"),\n\n        }\n    }\n\n    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {\n        channel = MethodChannel(\n            flutterPluginBinding.binaryMessenger,\n            channelName,\n        )\n        channel!!.setMethodCallHandler(this)\n    }\n\n    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {\n        channel?.setMethodCallHandler(null)\n    }\n\n    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {\n        when (call.method) {\n            Trigger.AddGrpcClientPublicKey.method -> {\n                GlobalScope.launch {\n                    result.runCatching {\n                        val args = call.arguments as Map<*, *>\n                        val clientPub = args[\"clientPublicKey\"] as ByteArray\n//                        Mobile.addGrpcClientPublicKey(clientPub)\n                        Settings.grpcFlutterPublicKey = clientPub\n                        success(\"\")\n\n                    }\n                }\n            }\n\n            Trigger.GetGrpcServerPublicKey.method -> {\n                GlobalScope.launch {\n                    result.runCatching {\n                        result.success(Mobile.getServerPublicKey())\n                    }\n                }\n            }\n\n            Trigger.Setup.method -> {\n                GlobalScope.launch {\n                    result.runCatching {\n                        val args = call.arguments as Map<*, *>\n                        Settings.baseDir = args[\"baseDir\"] as String\n                        Settings.workingDir = args[\"workingDir\"] as String\n                        Settings.tempDir = args[\"tempDir\"] as String\n                        Settings.debugMode = args[\"debug\"] as Boolean? ?: false\n                        val mode = args[\"mode\"] as Int\n                        val grpcPort = args[\"grpcPort\"] as Int\n                        Log.d(\"debugmode\",\"${Settings.debugMode}\")\n                        runCatching {\n                            Mobile.setup(\n                                SetupOptions().also {\n                                    it.basePath = Settings.baseDir\n                                    it.workingDir = Settings.workingDir\n                                    it.tempDir = Settings.tempDir\n                                    it.fixAndroidStack = Bugs.fixAndroidStack\n                                    it.mode=mode.toLong()\n                                    it.listen= \"127.0.0.1:\" + grpcPort\n                                    it.secret=\"\"\n                                    it.debug = Settings.debugMode\n                                },null)\n\n//                            Libbox.setup(Settings.baseDir, Settings.workingDir, Settings.tempDir, false)\n                            Libbox.redirectStderr(File(Settings.workingDir, \"stderr2.log\").path)\n\n                            success(\"\")\n                        }.onFailure {\n                            error(it)\n                        }\n\n                    }\n                }\n            }\n\n\n            Trigger.Start.method -> {\n                scope.launch {\n                    result.runCatching {\n                        val args = call.arguments as Map<*, *>\n                        Settings.activeConfigPath = args[\"path\"] as String? ?: \"\"\n                        Settings.activeProfileName = args[\"name\"] as String? ?: \"\"\n                        Settings.debugMode = args[\"debug\"] as Boolean? ?: false\n                        Settings.grpcServiceModePort = args[\"grpcPort\"] as Int\n\n                        val mainActivity = MainActivity.instance\n//                        val started = mainActivity.serviceStatus.value == Status.Started\n//                        if (started) {\n//                            Log.w(TAG, \"service is already running\")\n//                            return@launch success(true)\n//                        }\n                        Settings.startCoreAfterStartingService = false\n\n                        mainActivity.startService()\n                        success(true)\n                    }\n                }\n            }\n\n            Trigger.Stop.method -> {\n                scope.launch {\n                    result.runCatching {\n                        val mainActivity = MainActivity.instance\n                        val started = mainActivity.serviceStatus.value == Status.Started\n                        if (!started) {\n                            Log.w(TAG, \"service is not running\")\n                            //    return@launch success(true)\n                        }\n                        BoxService.stop()\n                        success(true)\n                    }\n                }\n            }\n\n//            Trigger.Restart.method -> {\n//                scope.launch(Dispatchers.IO) {\n//                    result.runCatching {\n//                        val args = call.arguments as Map<*, *>\n//                        Settings.activeConfigPath = args[\"path\"] as String? ?: \"\"\n//                        Settings.activeProfileName = args[\"name\"] as String? ?: \"\"\n//                        val mainActivity = MainActivity.instance\n//                        val started = mainActivity.serviceStatus.value == Status.Started\n//                        if (!started) return@launch success(true)\n//                        val restart = Settings.rebuildServiceMode()\n//                        if (restart) {\n//                            mainActivity.reconnect()\n//                            BoxService.stop()\n//                            delay(1000L)\n//                            mainActivity.startService()\n//                            return@launch success(true)\n//                        }\n//                        runCatching {\n//                            Libbox.newStandaloneCommandClient().serviceReload()\n//                            success(true)\n//                        }.onFailure {\n//                            error(it)\n//                        }\n//                    }\n//                }\n//            }\n\n            else -> result.notImplemented()\n        }\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/PlatformSettingsHandler.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.Manifest\nimport android.annotation.SuppressLint\nimport android.app.Activity\nimport android.content.Intent\nimport android.content.pm.ApplicationInfo\nimport android.content.pm.PackageManager\nimport android.graphics.Bitmap\nimport android.graphics.Canvas\nimport android.net.Uri\nimport android.os.Build\nimport android.util.Base64\nimport com.google.gson.Gson\nimport com.google.gson.annotations.SerializedName\nimport com.hiddify.hiddify.Application.Companion.packageManager\nimport io.flutter.embedding.engine.plugins.FlutterPlugin\nimport io.flutter.embedding.engine.plugins.activity.ActivityAware\nimport io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding\nimport io.flutter.plugin.common.MethodCall\nimport io.flutter.plugin.common.MethodChannel\nimport io.flutter.plugin.common.PluginRegistry\nimport io.flutter.plugin.common.StandardMethodCodec\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.launch\nimport java.io.ByteArrayOutputStream\n\n\nclass PlatformSettingsHandler : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware,\n    PluginRegistry.ActivityResultListener {\n    private var channel: MethodChannel? = null\n    private var activity: Activity? = null\n    private lateinit var ignoreRequestResult: MethodChannel.Result\n\n    companion object {\n        const val channelName = \"com.hiddify.app/platform\"\n\n        const val REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = 44\n        val gson = Gson()\n\n        enum class Trigger(val method: String) {\n            IsIgnoringBatteryOptimizations(\"is_ignoring_battery_optimizations\"),\n            RequestIgnoreBatteryOptimizations(\"request_ignore_battery_optimizations\"),\n            GetInstalledPackages(\"get_installed_packages\"),\n            GetPackagesIcon(\"get_package_icon\"),\n        }\n    }\n\n    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {\n        val taskQueue = flutterPluginBinding.binaryMessenger.makeBackgroundTaskQueue()\n        channel = MethodChannel(\n            flutterPluginBinding.binaryMessenger,\n            channelName,\n            StandardMethodCodec.INSTANCE,\n            taskQueue\n        )\n        channel!!.setMethodCallHandler(this)\n    }\n\n    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {\n        channel?.setMethodCallHandler(null)\n    }\n\n    override fun onAttachedToActivity(binding: ActivityPluginBinding) {\n        activity = binding.activity\n        binding.addActivityResultListener(this)\n    }\n\n    override fun onDetachedFromActivityForConfigChanges() {\n        activity = null\n    }\n\n    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {\n        activity = binding.activity\n        binding.addActivityResultListener(this)\n    }\n\n    override fun onDetachedFromActivity() {\n        activity = null\n    }\n\n    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {\n        if (requestCode == REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) {\n            ignoreRequestResult.success(resultCode == Activity.RESULT_OK)\n            return true\n        }\n        return false\n    }\n\n    data class AppItem(\n        @SerializedName(\"package-name\") val packageName: String,\n        @SerializedName(\"name\") val name: String,\n        @SerializedName(\"is-system-app\") val isSystemApp: Boolean\n    )\n\n    @SuppressLint(\"BatteryLife\")\n    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {\n        when (call.method) {\n            Trigger.IsIgnoringBatteryOptimizations.method -> {\n                result.runCatching {\n                    success(\n                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n                            Application.powerManager.isIgnoringBatteryOptimizations(Application.application.packageName)\n                        } else {\n                            true\n                        }\n                    )\n                }\n            }\n\n            Trigger.RequestIgnoreBatteryOptimizations.method -> {\n                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {\n                    return result.success(true)\n                }\n                val intent = Intent(\n                    android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,\n                    Uri.parse(\"package:${Application.application.packageName}\")\n                )\n                ignoreRequestResult = result\n                activity?.startActivityForResult(intent, REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)\n            }\n\n            Trigger.GetInstalledPackages.method -> {\n                GlobalScope.launch {\n                    result.runCatching {\n                        val flag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {\n                            PackageManager.GET_PERMISSIONS or PackageManager.MATCH_UNINSTALLED_PACKAGES\n                        } else {\n                            @Suppress(\"DEPRECATION\")\n                            PackageManager.GET_PERMISSIONS or PackageManager.GET_UNINSTALLED_PACKAGES\n                        }\n                        val installedPackages =\n                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {\n                                packageManager.getInstalledPackages(\n                                    PackageManager.PackageInfoFlags.of(\n                                        flag.toLong()\n                                    )\n                                )\n                            } else {\n                                @Suppress(\"DEPRECATION\")\n                                packageManager.getInstalledPackages(flag)\n                            }\n                        val list = mutableListOf<AppItem>()\n                        installedPackages.forEach {\n                            if (it.packageName != Application.application.packageName &&\n                                (it.requestedPermissions?.contains(Manifest.permission.INTERNET) == true\n                                        || it.packageName == \"android\")\n                            ) {\n                                list.add(\n                                    AppItem(\n                                        it.packageName,\n                                        it.applicationInfo?.loadLabel(packageManager).toString(),\n                                        (it.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM) == 1)\n                                    )\n                                )\n                            }\n                        }\n                        list.sortBy { it.name }\n                        success(gson.toJson(list))\n                    }\n                }\n            }\n\n            Trigger.GetPackagesIcon.method -> {\n                result.runCatching {\n                    val args = call.arguments as Map<*, *>\n                    val packageName =\n                        args[\"packageName\"] as String\n                    val drawable = packageManager.getApplicationIcon(packageName)\n                    val bitmap = Bitmap.createBitmap(\n                        drawable.intrinsicWidth,\n                        drawable.intrinsicHeight,\n                        Bitmap.Config.ARGB_8888\n                    )\n                    val canvas = Canvas(bitmap)\n                    drawable.setBounds(0, 0, canvas.width, canvas.height)\n                    drawable.draw(canvas)\n                    val byteArrayOutputStream = ByteArrayOutputStream()\n                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)\n                    val base64: String =\n                        Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.NO_WRAP)\n                    success(base64)\n                }\n            }\n\n            else -> result.notImplemented()\n        }\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/Settings.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.content.Context\nimport android.util.Base64\nimport com.hiddify.hiddify.bg.ProxyService\nimport com.hiddify.hiddify.bg.VPNService\nimport com.hiddify.hiddify.constant.PerAppProxyMode\nimport com.hiddify.hiddify.constant.ServiceMode\nimport com.hiddify.hiddify.constant.SettingsKey\nimport org.json.JSONObject\nimport java.io.ByteArrayInputStream\nimport java.io.File\nimport java.io.ObjectInputStream\n\n\nobject Settings {\n\n    private val preferences by lazy {\n        val context = Application.application.applicationContext\n        context.getSharedPreferences(\"FlutterSharedPreferences\", Context.MODE_PRIVATE)\n    }\n\n    private const val LIST_IDENTIFIER = \"VGhpcyBpcyB0aGUgcHJlZml4IGZvciBhIGxpc3Qu\"\n\n    var perAppProxyMode: String\n        get() = preferences.getString(SettingsKey.PER_APP_PROXY_MODE, PerAppProxyMode.OFF)!!\n        set(value) = preferences.edit().putString(SettingsKey.PER_APP_PROXY_MODE, value).apply()\n\n    val perAppProxyEnabled: Boolean\n        get() = perAppProxyMode != PerAppProxyMode.OFF\n\n    val perAppProxyList: List<String>\n        get() {\n            val stringValue = if (perAppProxyMode == PerAppProxyMode.INCLUDE) {\n                preferences.getString(SettingsKey.PER_APP_PROXY_INCLUDE_LIST, \"\")!!\n            } else {\n                preferences.getString(SettingsKey.PER_APP_PROXY_EXCLUDE_LIST, \"\")!!\n            }\n            if (!stringValue.startsWith(LIST_IDENTIFIER)) {\n                return stringValue.split(\";\")\n            }\n            return try {\n                decodeListString(stringValue.substring(LIST_IDENTIFIER.length))\n            } catch (e: java.lang.Exception) {\n                emptyList()\n            }\n        }\n\n    private fun decodeListString(listString: String): List<String> {\n        val stream = ObjectInputStream(ByteArrayInputStream(Base64.decode(listString, 0)))\n        return stream.readObject() as List<String>\n    }\n\n    var activeConfigPath: String\n        get() = preferences.getString(SettingsKey.ACTIVE_CONFIG_PATH, \"\")!!\n        set(value) = preferences.edit().putString(SettingsKey.ACTIVE_CONFIG_PATH, value).apply()\n\n    var activeProfileName: String\n        get() = preferences.getString(SettingsKey.ACTIVE_PROFILE_NAME, \"\")!!\n        set(value) = preferences.edit().putString(SettingsKey.ACTIVE_PROFILE_NAME, value).apply()\n\n    var serviceMode: String\n        get() = preferences.getString(SettingsKey.SERVICE_MODE, ServiceMode.VPN)!!\n        set(value) = preferences.edit().putString(SettingsKey.SERVICE_MODE, value).apply()\n\n    var configOptions: String\n        get() = preferences.getString(SettingsKey.CONFIG_OPTIONS, \"\")!!\n        set(value) = preferences.edit().putString(SettingsKey.CONFIG_OPTIONS, value).apply()\n\n    var debugMode: Boolean\n        get() = preferences.getBoolean(SettingsKey.DEBUG_MODE, false)\n        set(value) = preferences.edit().putBoolean(SettingsKey.DEBUG_MODE, value).apply()\n\n    var disableMemoryLimit: Boolean\n        get() = preferences.getBoolean(SettingsKey.DISABLE_MEMORY_LIMIT, false)\n        set(value) =\n            preferences.edit().putBoolean(SettingsKey.DISABLE_MEMORY_LIMIT, value).apply()\n\n    var dynamicNotification: Boolean\n        get() = preferences.getBoolean(SettingsKey.DYNAMIC_NOTIFICATION, true)\n        set(value) =\n            preferences.edit().putBoolean(SettingsKey.DYNAMIC_NOTIFICATION, value).apply()\n\n    var systemProxyEnabled: Boolean\n        get() = preferences.getBoolean(SettingsKey.SYSTEM_PROXY_ENABLED, true)\n        set(value) =\n            preferences.edit().putBoolean(SettingsKey.SYSTEM_PROXY_ENABLED, value).apply()\n\n    var startedByUser: Boolean\n        get() = preferences.getBoolean(SettingsKey.STARTED_BY_USER, false)\n        set(value) = preferences.edit().putBoolean(SettingsKey.STARTED_BY_USER, value).apply()\n\n    fun serviceClass(): Class<*> {\n        return when (serviceMode) {\n            ServiceMode.VPN -> VPNService::class.java\n            else -> ProxyService::class.java\n        }\n    }\n\n    private var currentServiceMode : String? = null\n\n    suspend fun rebuildServiceMode(): Boolean {\n        var newMode = ServiceMode.NORMAL\n        try {\n            if (serviceMode == ServiceMode.VPN) {\n                newMode = ServiceMode.VPN\n            }\n        } catch (_: Exception) {\n        }\n        if (currentServiceMode == newMode) {\n            return false\n        }\n        currentServiceMode = newMode\n        return true\n    }\n\n    private suspend fun needVPNService(): Boolean {\n        val filePath = activeConfigPath\n        if (filePath.isBlank()) return false\n        val content = JSONObject(File(filePath).readText())\n        val inbounds = content.getJSONArray(\"inbounds\")\n        for (index in 0 until inbounds.length()) {\n            val inbound = inbounds.getJSONObject(index)\n            if (inbound.getString(\"type\") == \"tun\") {\n                return true\n            }\n        }\n        return false\n    }\n\n    var workingDir: String\n        get() = preferences.getString(SettingsKey.WORKING_DIR, \"./\")!!\n        set(value) = preferences.edit().putString(SettingsKey.WORKING_DIR, value).apply()\n    var tempDir: String\n        get() = preferences.getString(SettingsKey.TMP_DIR, \"./\")!!\n        set(value) = preferences.edit().putString(SettingsKey.TMP_DIR, value).apply()\n\n    var baseDir: String\n        get() = preferences.getString(SettingsKey.BASE_DIR, \"./\")!!\n        set(value) = preferences.edit().putString(SettingsKey.BASE_DIR, value).apply()\n\n\n\n    var grpcFlutterPublicKey: ByteArray\n        get() {\n            val encoded = preferences.getString(SettingsKey.GRPC_FLUTTER_PUBLIC_KEY, null)\n            return encoded?.let { Base64.decode(it, Base64.DEFAULT) } ?: ByteArray(0)\n        }\n        set(value) {\n            val encoded = Base64.encodeToString(value, Base64.DEFAULT)\n            preferences.edit().putString(SettingsKey.GRPC_FLUTTER_PUBLIC_KEY, encoded).apply()\n        }\n    var grpcServiceModePort: Int\n        get() = preferences.getInt(SettingsKey.GRPC_PORT, 17078)!!\n        set(value) = preferences.edit().putInt(SettingsKey.GRPC_PORT, value).apply()\n\n    var startCoreAfterStartingService: Boolean\n        get() = preferences.getBoolean(SettingsKey.START_CORE_ON_STARTING_SERVICE, false)\n        set(value) = preferences.edit().putBoolean(SettingsKey.START_CORE_ON_STARTING_SERVICE, value).apply()\n\n\n}\n\n"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/ShortcutActivity.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.app.Activity\nimport android.content.Intent\nimport android.content.pm.ShortcutManager\nimport android.os.Build\nimport android.os.Bundle\nimport androidx.core.content.getSystemService\nimport androidx.core.content.pm.ShortcutInfoCompat\nimport androidx.core.content.pm.ShortcutManagerCompat\nimport androidx.core.graphics.drawable.IconCompat\nimport com.hiddify.hiddify.bg.BoxService\nimport com.hiddify.hiddify.bg.ServiceConnection\nimport com.hiddify.hiddify.constant.Status\n\nclass ShortcutActivity : Activity(), ServiceConnection.Callback {\n\n    private val connection = ServiceConnection(this, this, false)\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        if (intent.action == Intent.ACTION_CREATE_SHORTCUT) {\n            setResult(\n                RESULT_OK, ShortcutManagerCompat.createShortcutResultIntent(\n                    this,\n                    ShortcutInfoCompat.Builder(this, \"toggle\")\n                        .setIntent(\n                            Intent(\n                                this,\n                                ShortcutActivity::class.java\n                            ).setAction(Intent.ACTION_MAIN)\n                        )\n                        .setIcon(\n                            IconCompat.createWithResource(\n                                this,\n                                R.mipmap.ic_launcher\n                            )\n                        )\n                        .setShortLabel(getString(R.string.quick_toggle))\n                        .build()\n                )\n            )\n            finish()\n        } else {\n            connection.connect()\n            if (Build.VERSION.SDK_INT >= 25) {\n                getSystemService<ShortcutManager>()?.reportShortcutUsed(\"toggle\")\n            }\n        }\n        moveTaskToBack(true)\n    }\n\n    override fun onServiceStatusChanged(status: Status) {\n        when (status) {\n            Status.Started -> BoxService.stop()\n            Status.Stopped -> BoxService.start()\n            else -> {}\n        }\n        finish()\n    }\n\n    override fun onDestroy() {\n        connection.disconnect()\n        super.onDestroy()\n    }\n\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/StatsChannel.kt",
    "content": "package com.hiddify.hiddify\n\nimport android.util.Log\n//import com.hiddify.hiddify.utils.CommandClient\nimport io.flutter.embedding.engine.plugins.FlutterPlugin\nimport io.flutter.plugin.common.EventChannel\nimport io.flutter.plugin.common.JSONMethodCodec\nimport com.hiddify.core.libbox.StatusMessage\nimport kotlinx.coroutines.CoroutineScope\n\n//class StatsChannel(private val scope: CoroutineScope) : FlutterPlugin, CommandClient.Handler{\n//    companion object {\n//        const val TAG = \"A/StatsChannel\"\n//        const val STATS_CHANNEL = \"com.hiddify.app/stats\"\n//    }\n//\n//    private val commandClient =\n//            CommandClient(scope, CommandClient.ConnectionType.Status, this)\n//\n//    private var statsChannel: EventChannel? = null\n//    private var statsEvent: EventChannel.EventSink? = null\n//\n//    override fun updateStatus(status: StatusMessage) {\n//        MainActivity.instance.runOnUiThread {\n//            val map = listOf(\n//                    Pair(\"connections-in\", status.connectionsIn),\n//                    Pair(\"connections-out\", status.connectionsOut),\n//                    Pair(\"uplink\", status.uplink),\n//                    Pair(\"downlink\", status.downlink),\n//                    Pair(\"uplink-total\", status.uplinkTotal),\n//                    Pair(\"downlink-total\", status.downlinkTotal)\n//            ).associate { it.first to it.second }\n//            statsEvent?.success(map)\n//        }\n//    }\n//\n//    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {\n//        statsChannel = EventChannel(\n//                flutterPluginBinding.binaryMessenger,\n//                STATS_CHANNEL,\n//                JSONMethodCodec.INSTANCE\n//        )\n//\n//        statsChannel!!.setStreamHandler(object : EventChannel.StreamHandler {\n//            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {\n//                statsEvent = events\n//                Log.d(TAG, \"connecting stats command client\")\n//                commandClient.connect()\n//            }\n//\n//            override fun onCancel(arguments: Any?) {\n//                statsEvent = null\n//                Log.d(TAG, \"disconnecting stats command client\")\n//                commandClient.disconnect()\n//            }\n//        })\n//    }\n//\n//    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {\n//        statsEvent = null\n//        commandClient.disconnect()\n//        statsChannel?.setStreamHandler(null)\n//    }\n//}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/AppChangeReceiver.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport com.hiddify.hiddify.Settings\n\nclass AppChangeReceiver : BroadcastReceiver() {\n\n    companion object {\n        private const val TAG = \"A/AppChangeReceiver\"\n    }\n\n    override fun onReceive(context: Context, intent: Intent) {\n        checkUpdate(context, intent)\n    }\n\n    private fun checkUpdate(context: Context, intent: Intent) {\n//        if (!Settings.perAppProxyEnabled) {\n//            return\n//        }\n//        val perAppProxyUpdateOnChange = Settings.perAppProxyUpdateOnChange\n//        if (perAppProxyUpdateOnChange == Settings.PER_APP_PROXY_DISABLED) {\n//            return\n//        }\n//        val packageName = intent.dataString?.substringAfter(\"package:\")\n//        if (packageName.isNullOrBlank()) {\n//            return\n//        }\n//        if ((perAppProxyUpdateOnChange == Settings.PER_APP_PROXY_INCLUDE)) {\n//            Settings.perAppProxyList = Settings.perAppProxyList + packageName\n//        } else {\n//            Settings.perAppProxyList = Settings.perAppProxyList - packageName\n//        }\n    }\n\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/BootReceiver.kt",
    "content": "package com.hiddify.hiddify.bg\nimport android.content.BroadcastReceiver\nimport android.content.Context\n\nimport android.content.Intent\nimport com.hiddify.hiddify.MainActivity\nimport com.hiddify.hiddify.Settings\nimport kotlinx.coroutines.DelicateCoroutinesApi\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\n\nclass BootReceiver : BroadcastReceiver() {\n    @OptIn(DelicateCoroutinesApi::class)\n    override fun onReceive(context: Context, intent: Intent) {\n        when (intent.action) {\n            Intent.ACTION_BOOT_COMPLETED, Intent.ACTION_MY_PACKAGE_REPLACED -> {\n            }\n\n            else -> return\n        }\n        GlobalScope.launch(Dispatchers.IO) {\n            if (Settings.startedByUser) {\n                withContext(Dispatchers.Main) {\n                    Settings.startCoreAfterStartingService=true //H\n                    BoxService.start()\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/BoxService.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.app.NotificationChannel\nimport android.app.NotificationManager\nimport android.app.PendingIntent\nimport android.app.Service\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport android.content.IntentFilter\nimport android.net.Uri\nimport android.os.Build\nimport android.os.IBinder\nimport android.os.ParcelFileDescriptor\nimport android.os.PowerManager\nimport android.util.Log\nimport androidx.annotation.RequiresApi\nimport androidx.core.app.NotificationCompat\nimport androidx.core.content.ContextCompat\nimport androidx.lifecycle.MutableLiveData\nimport com.hiddify.hiddify.Application\nimport com.hiddify.hiddify.R\nimport com.hiddify.hiddify.Settings\nimport com.hiddify.hiddify.constant.Action\nimport com.hiddify.hiddify.constant.Alert\nimport com.hiddify.hiddify.constant.Status\nimport com.hiddify.core.mobile.SetupOptions\n\nimport go.Seq\nimport com.hiddify.core.libbox.Libbox\nimport com.hiddify.core.mobile.Mobile\n\n\nimport com.hiddify.core.libbox.CommandServer\nimport com.hiddify.core.libbox.CommandServerHandler\nimport com.hiddify.core.libbox.Notification\nimport com.hiddify.core.libbox.PlatformInterface\nimport com.hiddify.core.libbox.SystemProxyStatus\nimport com.hiddify.hiddify.BuildConfig\nimport com.hiddify.hiddify.MainActivity\nimport com.hiddify.hiddify.constant.Bugs\nimport kotlinx.coroutines.DelicateCoroutinesApi\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.runBlocking\nimport kotlinx.coroutines.withContext\nimport java.io.File\n\nclass BoxService(\n        private val service: Service,\n        private val platformInterface: PlatformInterface\n)  {\n\n    companion object {\n        private const val TAG = \"A/BoxService\"\n\n        private var initializeOnce = false\n        private lateinit var workingDir: File\n        private fun initialize() {\n            System.setProperty(\"GODEBUG\", \"efence=1,stacktraceback=2\");\n            System.setProperty(\"GOGC\", \"off\");\n            if (initializeOnce) return\n            val baseDir = Application.application.filesDir\n\n            baseDir.mkdirs()\n            workingDir = Application.application.getExternalFilesDir(null) ?: return\n            workingDir.mkdirs()\n            val tempDir = Application.application.cacheDir\n            tempDir.mkdirs()\n            Log.d(TAG, \"base dir: ${baseDir.path}\")\n            Log.d(TAG, \"working dir: ${workingDir.path}\")\n            Log.d(TAG, \"temp dir: ${tempDir.path}\")\n\n//\n            //Mobile.setup(baseDir.path, workingDir.path, tempDir.path,  2L ,\"127.0.0.1:{Setting}\",\"\",false,this)\n//            Libbox.setup(baseDir.path, workingDir.path, tempDir.path, false)\n\n//            Libbox.setup(SetupOptions().also {\n//                it.basePath = baseDir.path\n//                it.workingPath = workingDir.path\n//                it.tempPath = tempDir.path\n//                it.fixAndroidStack = Bugs.fixAndroidStack\n//\n//            })\n            Libbox.redirectStderr(File(Settings.workingDir, \"stderr.log\").path)\n            initializeOnce = true\n            return\n        }\n\n        fun start() {\n            val intent = runBlocking {\n                withContext(Dispatchers.IO) {\n                    Intent(Application.application, Settings.serviceClass())\n                }\n            }\n            ContextCompat.startForegroundService(Application.application, intent)\n        }\n\n        fun stop() {\n            Application.application.sendBroadcast(\n                    Intent(Action.SERVICE_CLOSE).setPackage(\n                            Application.application.packageName\n                    )\n            )\n        }\n\n\n    }\n\n    var fileDescriptor: ParcelFileDescriptor? = null\n\n    private val status = MutableLiveData(Status.Stopped)\n    private val binder = ServiceBinder(status)\n    private val notification = ServiceNotification(status, service)\n//    private var boxService: BoxService? = null\n    private var commandServer: CommandServer? = null\n    private var receiverRegistered = false\n    private val receiver = object : BroadcastReceiver() {\n        override fun onReceive(context: Context, intent: Intent) {\n            when (intent.action) {\n                Action.SERVICE_CLOSE -> {\n                    stopService()\n                }\n\n                PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED -> {\n                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n                        serviceUpdateIdleMode()\n                    }\n                }\n            }\n        }\n    }\n    \n\n\n    private var activeProfileName = \"\"\n    private suspend fun startService() {\n        try {\n            status.postValue(Status.Starting)\n            Log.d(TAG, \"starting service\")\n            withContext(Dispatchers.Main) {\n                notification.show(activeProfileName, R.string.status_starting)\n            }\n\n            val selectedConfigPath = Settings.activeConfigPath\n            if (selectedConfigPath.isBlank()) {\n                stopAndAlert(Alert.EmptyConfiguration)\n                return\n            }\n\n            activeProfileName = Settings.activeProfileName\n\n            withContext(Dispatchers.Main) {\n                notification.show(activeProfileName, R.string.status_starting)\n                binder.broadcast {\n                    it.onServiceResetLogs(listOf())\n                }\n            }\n\n            DefaultNetworkMonitor.start()\n            Libbox.setMemoryLimit(!Settings.disableMemoryLimit)\n            val newService = try {\n                Mobile.setup(\n                    SetupOptions().also {\n                        it.basePath = Settings.baseDir\n                        it.workingDir = Settings.workingDir\n                        it.tempDir = Settings.tempDir\n                        it.fixAndroidStack = com.hiddify.hiddify.bg.Bugs.fixAndroidStack\n                        it.mode=4L//mode.toLong()\n                        it.listen= \"127.0.0.1:${Settings.grpcServiceModePort}\"\n                        it.secret=\"\"\n                        it.debug = Settings.debugMode\n                    },platformInterface)\n\n\n//                Libbox.newService(content,platformInterface)\n\n            } catch (e: Exception) {\n                stopAndAlert(Alert.CreateService, e.message)\n                return\n            }\n            status.postValue(Status.Started)\n\n            if (Settings.startCoreAfterStartingService){\n                Mobile.start(\"\",\"\")\n                }\n//            if (delayStart) {\n//                delay(1000L)\n//            }\n\n//            newService.start()\n//            boxService = newService\n//            commandServer?.setService(boxService)\n\n\n            withContext(Dispatchers.Main) {\n                notification.show(activeProfileName, R.string.status_started)\n            }\n            notification.start()\n        } catch (e: Exception) {\n            stopAndAlert(Alert.StartService, e.message)\n            return\n        }\n    }\n\n    fun serviceReload() {\n        runBlocking {\n            serviceReload0()\n        }\n    }\n\n    suspend fun serviceReload0() {\n        notification.close()\n        status.postValue(Status.Starting)\n\n        val pfd = fileDescriptor\n        if (pfd != null) {\n            pfd.close()\n            fileDescriptor = null\n        }\n        \n//        boxService?.apply {\n//            runCatching {\n//                close()\n//            }.onFailure {\n//                writeLog(\"service: error when closing: $it\")\n//            }\n//            Seq.destroyRef(refnum)\n//        }\n        Mobile.stop()\n//        boxService = null\n        \n            startService()\n        \n    }\n\n    fun getSystemProxyStatus(): SystemProxyStatus {\n        val status = SystemProxyStatus()\n        if (service is VPNService) {\n            status.available = service.systemProxyAvailable\n            status.enabled = service.systemProxyEnabled\n        }\n        return status\n    }\n\n    fun setSystemProxyEnabled(isEnabled: Boolean) {\n        serviceReload()\n    }\n\n    @RequiresApi(Build.VERSION_CODES.M)\n    private fun serviceUpdateIdleMode() {\n        if (Application.powerManager.isDeviceIdleMode) {\n//            boxService?.pause()\n            //Mobile.pause()\n        } else {\n            Mobile.wake()\n//            boxService?.wake()\n        }\n    }\n\n    private fun stopService() {\n        if (status.value == Status.Stopped) return\n        status.value = Status.Stopping\n        if (receiverRegistered) {\n            service.unregisterReceiver(receiver)\n            receiverRegistered = false\n        }\n        notification.close()\n        GlobalScope.launch(Dispatchers.IO) {\n            val pfd = fileDescriptor\n            if (pfd != null) {\n                pfd.close()\n                fileDescriptor = null\n            }\n//            commandServer?.setService(null)\n//            boxService?.apply {\n//                runCatching {\n//                    close()\n//                }.onFailure {\n//                    writeLog(\"service: error when closing: $it\")\n//                }\n//                //Seq.destroyRef(refnum)\n//            }\n\n//            boxService = null\n//            Libbox.registerLocalDNSTransport(null)\n            DefaultNetworkMonitor.stop()\n\n//            commandServer?.apply {\n//                close()\n//                Seq.destroyRef(refnum)\n//            }\n//            commandServer = null\n            Settings.startedByUser = false\n            withContext(Dispatchers.Main) {\n                Mobile.close(4L)\n                status.value = Status.Stopped\n                service.stopSelf()\n            }\n            notification.close()\n        }\n    }\n\n    private suspend fun stopAndAlert(type: Alert, message: String? = null) {\n        Settings.startedByUser = false\n        withContext(Dispatchers.Main) {\n            if (receiverRegistered) {\n                service.unregisterReceiver(receiver)\n                receiverRegistered = false\n            }\n            notification.close()\n            binder.broadcast { callback ->\n                callback.onServiceAlert(type.ordinal, message)\n            }\n            status.value = Status.Stopped\n        }\n    }\n\n    @OptIn(DelicateCoroutinesApi::class)\n    @Suppress(\"SameReturnValue\")\n    internal fun onStartCommand(): Int {\n        if (status.value != Status.Stopped) return Service.START_NOT_STICKY\n        status.value = Status.Starting\n\n        if (!receiverRegistered) {\n            ContextCompat.registerReceiver(service, receiver, IntentFilter().apply {\n                addAction(Action.SERVICE_CLOSE)\n                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n                    addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)\n                }\n            }, ContextCompat.RECEIVER_NOT_EXPORTED)\n            receiverRegistered = true\n        }\n\n        GlobalScope.launch(Dispatchers.IO) {\n            Settings.startedByUser = true\n            initialize()\n//            try {\n//                startCommandServer()\n//            } catch (e: Exception) {\n//                stopAndAlert(Alert.StartCommandServer, e.message)\n//                return@launch\n//            }\n            startService()\n        }\n        return Service.START_NOT_STICKY\n    }\n\n    fun onBind(intent: Intent): IBinder {\n        return binder\n    }\n\n    fun onDestroy() {\n        binder.close()\n    }\n\n    fun onRevoke() {\n        stopService()\n    }\n\n    internal fun sendNotification(notification: Notification) {\n        return\n        val builder =\n            NotificationCompat.Builder(service, notification.identifier).setShowWhen(false)\n                .setContentTitle(notification.title).setContentText(notification.body)\n                .setOnlyAlertOnce(true).setSmallIcon(R.drawable.ic_launcher_foreground)\n                .setCategory(NotificationCompat.CATEGORY_EVENT)\n                .setPriority(NotificationCompat.PRIORITY_HIGH).setAutoCancel(true)\n        if (!notification.subtitle.isNullOrBlank()) {\n            builder.setContentInfo(notification.subtitle)\n        }\n        if (!notification.openURL.isNullOrBlank()) {\n            builder.setContentIntent(\n                PendingIntent.getActivity(\n                    service,\n                    0,\n                    Intent(\n                        service,\n                        MainActivity::class.java,\n                    ).apply {\n                        setAction(Action.SERVICE).setData(Uri.parse(notification.openURL))\n                        setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)\n                    },\n                    ServiceNotification.flags,\n                ),\n            )\n        }\n        GlobalScope.launch(Dispatchers.Main) {\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n                Application.notification.createNotificationChannel(\n                    NotificationChannel(\n                        notification.identifier,\n                        notification.typeName,\n                        NotificationManager.IMPORTANCE_HIGH,\n                    ),\n                )\n            }\n            Application.notification.notify(notification.typeID, builder.build())\n        }\n    }\n\n     fun writeDebugMessage(message: String?) {\n        Log.d(\"BoxService\", message!!)\n        binder.broadcast {\n            it.onServiceWriteLog(message)\n        }\n    }\n\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/Bugs.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.os.Build\nimport com.hiddify.hiddify.BuildConfig\n\n\nobject Bugs {\n    // TODO: remove launch after fixed\n    // https://github.com/golang/go/issues/68760\n    val fixAndroidStack =\n        BuildConfig.DEBUG ||\n                Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&\n                Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 ||\n                Build.VERSION.SDK_INT >= Build.VERSION_CODES.P\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/DefaultNetworkListener.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.annotation.TargetApi\nimport android.net.ConnectivityManager\nimport android.net.Network\nimport android.net.NetworkCapabilities\nimport android.net.NetworkRequest\nimport android.os.Build\nimport android.os.Handler\nimport android.os.Looper\nimport com.hiddify.hiddify.Application\nimport kotlinx.coroutines.CompletableDeferred\nimport kotlinx.coroutines.DelicateCoroutinesApi\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.ObsoleteCoroutinesApi\nimport kotlinx.coroutines.channels.actor\nimport kotlinx.coroutines.runBlocking\nimport java.net.UnknownHostException\n\n\nobject DefaultNetworkListener {\n    private sealed class NetworkMessage {\n        class Start(val key: Any, val listener: (Network?) -> Unit) : NetworkMessage()\n\n        class Get : NetworkMessage() {\n            val response = CompletableDeferred<Network>()\n        }\n\n        class Stop(val key: Any) : NetworkMessage()\n\n        class Put(val network: Network) : NetworkMessage()\n\n        class Update(val network: Network) : NetworkMessage()\n\n        class Lost(val network: Network) : NetworkMessage()\n    }\n\n    @OptIn(DelicateCoroutinesApi::class, ObsoleteCoroutinesApi::class)\n    private val networkActor =\n        GlobalScope.actor<NetworkMessage>(Dispatchers.Unconfined) {\n            val listeners = mutableMapOf<Any, (Network?) -> Unit>()\n            var network: Network? = null\n            val pendingRequests = arrayListOf<NetworkMessage.Get>()\n            for (message in channel) {\n                when (message) {\n                    is NetworkMessage.Start -> {\n                        if (listeners.isEmpty()) register()\n                        listeners[message.key] = message.listener\n                        if (network != null) message.listener(network)\n                    }\n\n                    is NetworkMessage.Get -> {\n                        check(listeners.isNotEmpty()) { \"Getting network without any listeners is not supported\" }\n                        if (network == null) {\n                            pendingRequests += message\n                        } else {\n                            message.response.complete(\n                                network,\n                            )\n                        }\n                    }\n\n                    is NetworkMessage.Stop ->\n                        if (listeners.isNotEmpty() &&\n                            // was not empty\n                            listeners.remove(message.key) != null &&\n                            listeners.isEmpty()\n                        ) {\n                            network = null\n                            unregister()\n                        }\n\n                    is NetworkMessage.Put -> {\n                        network = message.network\n                        pendingRequests.forEach { it.response.complete(message.network) }\n                        pendingRequests.clear()\n                        listeners.values.forEach { it(network) }\n                    }\n\n                    is NetworkMessage.Update ->\n                        if (network == message.network) {\n                            listeners.values.forEach {\n                                it(\n                                    network,\n                                )\n                            }\n                        }\n\n                    is NetworkMessage.Lost ->\n                        if (network == message.network) {\n                            network = null\n                            listeners.values.forEach { it(null) }\n                        }\n                }\n            }\n        }\n\n    suspend fun start(key: Any, listener: (Network?) -> Unit) = networkActor.send(\n        NetworkMessage.Start(\n            key,\n            listener,\n        ),\n    )\n\n    suspend fun get(): Network = if (fallback) {\n        @TargetApi(23)\n        Application.connectivity.activeNetwork\n            ?: error(\"missing default network\") // failed to listen, return current if available\n    } else {\n        NetworkMessage.Get().run {\n            networkActor.send(this)\n            response.await()\n        }\n    }\n\n    suspend fun stop(key: Any) = networkActor.send(NetworkMessage.Stop(key))\n\n    // NB: this runs in ConnectivityThread, and this behavior cannot be changed until API 26\n    private object Callback : ConnectivityManager.NetworkCallback() {\n        override fun onAvailable(network: Network) = runBlocking {\n            networkActor.send(\n                NetworkMessage.Put(\n                    network,\n                ),\n            )\n        }\n\n        override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {\n            // it's a good idea to refresh capabilities\n            runBlocking { networkActor.send(NetworkMessage.Update(network)) }\n        }\n\n        override fun onLost(network: Network) = runBlocking {\n            networkActor.send(\n                NetworkMessage.Lost(\n                    network,\n                ),\n            )\n        }\n    }\n\n    private var fallback = false\n    private val request =\n        NetworkRequest.Builder().apply {\n            addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)\n            addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)\n            if (Build.VERSION.SDK_INT == 23) { // workarounds for OEM bugs\n                removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)\n                removeCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)\n            }\n        }.build()\n    private val mainHandler = Handler(Looper.getMainLooper())\n\n    /**\n     * Unfortunately registerDefaultNetworkCallback is going to return VPN interface since Android P DP1:\n     * https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e\n     *\n     * This makes doing a requestNetwork with REQUEST necessary so that we don't get ALL possible networks that\n     * satisfies default network capabilities but only THE default network. Unfortunately, we need to have\n     * android.permission.CHANGE_NETWORK_STATE to be able to call requestNetwork.\n     *\n     * Source: https://android.googlesource.com/platform/frameworks/base/+/2df4c7d/services/core/java/com/android/server/ConnectivityService.java#887\n     */\n    private fun register() {\n        when (Build.VERSION.SDK_INT) {\n            in 31..Int.MAX_VALUE ->\n                @TargetApi(31)\n                {\n                    Application.connectivity.registerBestMatchingNetworkCallback(\n                        request,\n                        Callback,\n                        mainHandler,\n                    )\n                }\n\n            in 28 until 31 ->\n                @TargetApi(28)\n                { // we want REQUEST here instead of LISTEN\n                    Application.connectivity.requestNetwork(request, Callback, mainHandler)\n                }\n\n            in 26 until 28 ->\n                @TargetApi(26)\n                {\n                    Application.connectivity.registerDefaultNetworkCallback(Callback, mainHandler)\n                }\n\n            in 24 until 26 ->\n                @TargetApi(24)\n                {\n                    Application.connectivity.registerDefaultNetworkCallback(Callback)\n                }\n\n            else ->\n                try {\n                    fallback = false\n                    Application.connectivity.requestNetwork(request, Callback)\n                } catch (e: RuntimeException) {\n                    fallback =\n                        true // known bug on API 23: https://stackoverflow.com/a/33509180/2245107\n                }\n        }\n    }\n\n    private fun unregister() {\n        runCatching {\n            Application.connectivity.unregisterNetworkCallback(Callback)\n        }\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/DefaultNetworkMonitor.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.net.Network\nimport android.os.Build\nimport com.hiddify.hiddify.Application\nimport com.hiddify.core.libbox.InterfaceUpdateListener\nimport com.hiddify.hiddify.constant.Bugs\n\n\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.launch\nimport java.net.NetworkInterface\n\nobject DefaultNetworkMonitor {\n\n    var defaultNetwork: Network? = null\n    private var listener: InterfaceUpdateListener? = null\n\n    suspend fun start() {\n        DefaultNetworkListener.start(this) {\n            defaultNetwork = it\n            checkDefaultInterfaceUpdate(it)\n        }\n        defaultNetwork = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n            Application.connectivity.activeNetwork\n        } else {\n            DefaultNetworkListener.get()\n        }\n    }\n\n    suspend fun stop() {\n        DefaultNetworkListener.stop(this)\n    }\n\n    suspend fun require(): Network {\n        val network = defaultNetwork\n        if (network != null) {\n            return network\n        }\n        return DefaultNetworkListener.get()\n    }\n\n    fun setListener(listener: InterfaceUpdateListener?) {\n        this.listener = listener\n        checkDefaultInterfaceUpdate(defaultNetwork)\n    }\n\n    private fun checkDefaultInterfaceUpdate(newNetwork: Network?) {\n        val listener = listener ?: return\n        if (newNetwork != null) {\n            val interfaceName =\n                (Application.connectivity.getLinkProperties(newNetwork) ?: return).interfaceName\n            for (times in 0 until 10) {\n                var interfaceIndex: Int\n                try {\n                    interfaceIndex = NetworkInterface.getByName(interfaceName).index\n                } catch (e: Exception) {\n                    Thread.sleep(100)\n                    continue\n                }\n                listener.updateDefaultInterface(interfaceName, interfaceIndex, false, false)\n            }\n        } else {\n            listener.updateDefaultInterface(\"\", -1, false, false)\n        }\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/LocalResolver.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.net.DnsResolver\nimport android.os.Build\nimport android.os.CancellationSignal\nimport android.system.ErrnoException\nimport androidx.annotation.RequiresApi\nimport com.hiddify.hiddify.ktx.tryResumeWithException\nimport com.hiddify.core.libbox.ExchangeContext\nimport com.hiddify.core.libbox.LocalDNSTransport\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.asExecutor\nimport kotlinx.coroutines.runBlocking\nimport java.net.InetAddress\nimport java.net.UnknownHostException\nimport kotlin.coroutines.resume\nimport kotlin.coroutines.suspendCoroutine\n\nobject LocalResolver : LocalDNSTransport {\n    private const val RCODE_NXDOMAIN = 3\n\n    override fun raw(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q\n\n    @RequiresApi(Build.VERSION_CODES.Q)\n    override fun exchange(ctx: ExchangeContext, message: ByteArray) {\n        return runBlocking {\n            val defaultNetwork = DefaultNetworkMonitor.require()\n            suspendCoroutine { continuation ->\n                val signal = CancellationSignal()\n                ctx.onCancel(signal::cancel)\n                val callback =\n                    object : DnsResolver.Callback<ByteArray> {\n                        override fun onAnswer(answer: ByteArray, rcode: Int) {\n                            if (rcode == 0) {\n                                ctx.rawSuccess(answer)\n                            } else {\n                                ctx.errorCode(rcode)\n                            }\n                            continuation.resume(Unit)\n                        }\n\n                        override fun onError(error: DnsResolver.DnsException) {\n                            when (val cause = error.cause) {\n                                is ErrnoException -> {\n                                    ctx.errnoCode(cause.errno)\n                                    continuation.resume(Unit)\n                                    return\n                                }\n                            }\n                            continuation.tryResumeWithException(error)\n                        }\n                    }\n                DnsResolver.getInstance().rawQuery(\n                    defaultNetwork,\n                    message,\n                    DnsResolver.FLAG_NO_RETRY,\n                    Dispatchers.IO.asExecutor(),\n                    signal,\n                    callback,\n                )\n            }\n        }\n    }\n\n    override fun lookup(ctx: ExchangeContext, network: String, domain: String) {\n        return runBlocking {\n            val defaultNetwork = DefaultNetworkMonitor.require()\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {\n                suspendCoroutine { continuation ->\n                    val signal = CancellationSignal()\n                    ctx.onCancel(signal::cancel)\n                    val callback =\n                        object : DnsResolver.Callback<Collection<InetAddress>> {\n                            @Suppress(\"ThrowableNotThrown\")\n                            override fun onAnswer(answer: Collection<InetAddress>, rcode: Int) {\n                                if (rcode == 0) {\n                                    ctx.success(\n                                        (answer as Collection<InetAddress?>).mapNotNull { it?.hostAddress }\n                                            .joinToString(\"\\n\"),\n                                    )\n                                } else {\n                                    ctx.errorCode(rcode)\n                                }\n                                continuation.resume(Unit)\n                            }\n\n                            override fun onError(error: DnsResolver.DnsException) {\n                                when (val cause = error.cause) {\n                                    is ErrnoException -> {\n                                        ctx.errnoCode(cause.errno)\n                                        continuation.resume(Unit)\n                                        return\n                                    }\n                                }\n                                continuation.tryResumeWithException(error)\n                            }\n                        }\n                    val type =\n                        when {\n                            network.endsWith(\"4\") -> DnsResolver.TYPE_A\n                            network.endsWith(\"6\") -> DnsResolver.TYPE_AAAA\n                            else -> null\n                        }\n                    if (type != null) {\n                        DnsResolver.getInstance().query(\n                            defaultNetwork,\n                            domain,\n                            type,\n                            DnsResolver.FLAG_NO_RETRY,\n                            Dispatchers.IO.asExecutor(),\n                            signal,\n                            callback,\n                        )\n                    } else {\n                        DnsResolver.getInstance().query(\n                            defaultNetwork,\n                            domain,\n                            DnsResolver.FLAG_NO_RETRY,\n                            Dispatchers.IO.asExecutor(),\n                            signal,\n                            callback,\n                        )\n                    }\n                }\n            } else {\n                val answer =\n                    try {\n                        defaultNetwork.getAllByName(domain)\n                    } catch (e: UnknownHostException) {\n                        ctx.errorCode(RCODE_NXDOMAIN)\n                        return@runBlocking\n                    }\n                ctx.success(answer.mapNotNull { it.hostAddress }.joinToString(\"\\n\"))\n            }\n        }\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/PlatformInterfaceWrapper.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.annotation.SuppressLint\nimport android.content.pm.PackageManager\nimport android.net.NetworkCapabilities\nimport android.os.Build\nimport android.os.Process\nimport android.util.Log\nimport androidx.annotation.RequiresApi\nimport com.hiddify.hiddify.Application\nimport com.hiddify.core.libbox.InterfaceUpdateListener\nimport com.hiddify.core.libbox.Libbox\nimport com.hiddify.core.libbox.NetworkInterfaceIterator\nimport com.hiddify.core.libbox.PlatformInterface\nimport com.hiddify.core.libbox.StringIterator\nimport com.hiddify.core.libbox.TunOptions\nimport com.hiddify.core.libbox.WIFIState\nimport java.net.Inet6Address\nimport java.net.InetSocketAddress\nimport java.net.InterfaceAddress\nimport java.net.NetworkInterface\nimport java.util.Enumeration\nimport com.hiddify.core.libbox.NetworkInterface as LibboxNetworkInterface\n\n\n\nimport android.system.OsConstants\nimport com.hiddify.core.libbox.ConnectionOwner\nimport com.hiddify.core.libbox.LocalDNSTransport\nimport java.security.KeyStore\nimport kotlin.io.encoding.Base64\nimport kotlin.io.encoding.ExperimentalEncodingApi\n\ninterface PlatformInterfaceWrapper : PlatformInterface {\n    override fun usePlatformAutoDetectInterfaceControl(): Boolean = true\n\n    override fun autoDetectInterfaceControl(fd: Int) {\n    }\n\n    override fun openTun(options: TunOptions): Int {\n        error(\"invalid argument\")\n    }\n\n    override fun useProcFS(): Boolean =  Build.VERSION.SDK_INT < Build.VERSION_CODES.Q\n\n    @RequiresApi(Build.VERSION_CODES.Q)\n    override fun findConnectionOwner(\n        ipProtocol: Int,\n        sourceAddress: String,\n        sourcePort: Int,\n        destinationAddress: String,\n        destinationPort: Int,\n    ): ConnectionOwner {\n        try {\n            val uid =\n                Application.connectivity.getConnectionOwnerUid(\n                    ipProtocol,\n                    InetSocketAddress(sourceAddress, sourcePort),\n                    InetSocketAddress(destinationAddress, destinationPort),\n                )\n//            if (uid == Process.INVALID_UID)error(\"android: connection owner not found\")\n\n            val owner = ConnectionOwner()\n            owner.userId = uid\n            if (uid!=Process.INVALID_UID) {\n                val packages = Application.packageManager.getPackagesForUid(uid)\n                owner.userName = packages?.firstOrNull() ?: \"\"\n                owner.androidPackageName = owner.userName\n            }\n            return owner\n        } catch (e: Exception) {\n            Log.e(\"PlatformInterface\", \"getConnectionOwnerUid\", e)\n            e.printStackTrace(System.err)\n            throw e\n        }\n    }\n\n    override fun startDefaultInterfaceMonitor(listener: InterfaceUpdateListener) {\n        DefaultNetworkMonitor.setListener(listener)\n    }\n\n    override fun closeDefaultInterfaceMonitor(listener: InterfaceUpdateListener) {\n        DefaultNetworkMonitor.setListener(null)\n    }\n\n    override fun getInterfaces(): NetworkInterfaceIterator {\n        val networks = Application.connectivity.allNetworks\n        val networkInterfaces = NetworkInterface.getNetworkInterfaces().toList()\n        val interfaces = mutableListOf<LibboxNetworkInterface>()\n        for (network in networks) {\n            val boxInterface = LibboxNetworkInterface()\n            val linkProperties = Application.connectivity.getLinkProperties(network) ?: continue\n            val networkCapabilities =\n                Application.connectivity.getNetworkCapabilities(network) ?: continue\n            boxInterface.name = linkProperties.interfaceName\n            val networkInterface =\n                networkInterfaces.find { it.name == boxInterface.name } ?: continue\n            boxInterface.dnsServer =\n                StringArray(linkProperties.dnsServers.mapNotNull { it.hostAddress }.iterator())\n            boxInterface.type =\n                when {\n                    networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> Libbox.InterfaceTypeWIFI\n                    networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> Libbox.InterfaceTypeCellular\n                    networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> Libbox.InterfaceTypeEthernet\n                    else -> Libbox.InterfaceTypeOther\n                }\n            boxInterface.index = networkInterface.index\n            runCatching {\n                boxInterface.mtu = networkInterface.mtu\n            }.onFailure {\n                Log.e(\n                    \"PlatformInterface\",\n                    \"failed to get mtu for interface ${boxInterface.name}\",\n                    it,\n                )\n            }\n            boxInterface.addresses =\n                StringArray(\n                    networkInterface.interfaceAddresses.mapTo(mutableListOf()) { it.toPrefix() }\n                        .iterator(),\n                )\n            var dumpFlags = 0\n            if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {\n                dumpFlags = OsConstants.IFF_UP or OsConstants.IFF_RUNNING\n            }\n            if (networkInterface.isLoopback) {\n                dumpFlags = dumpFlags or OsConstants.IFF_LOOPBACK\n            }\n            if (networkInterface.isPointToPoint) {\n                dumpFlags = dumpFlags or OsConstants.IFF_POINTOPOINT\n            }\n            if (networkInterface.supportsMulticast()) {\n                dumpFlags = dumpFlags or OsConstants.IFF_MULTICAST\n            }\n            boxInterface.flags = dumpFlags\n            boxInterface.metered =\n                !networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)\n            interfaces.add(boxInterface)\n        }\n        return InterfaceArray(interfaces.iterator())\n    }\n\n    override fun underNetworkExtension(): Boolean = false\n\n    override fun includeAllNetworks(): Boolean = false\n\n    override fun clearDNSCache() {\n    }\n\n    override fun readWIFIState(): WIFIState? {\n        @Suppress(\"DEPRECATION\")\n        val wifiInfo =\n            Application.wifiManager.connectionInfo ?: return null\n        var ssid = wifiInfo.ssid\n        if (ssid == \"<unknown ssid>\") {\n            return WIFIState(\"\", \"\")\n        }\n        if (ssid.startsWith(\"\\\"\") && ssid.endsWith(\"\\\"\")) {\n            ssid = ssid.substring(1, ssid.length - 1)\n        }\n        return WIFIState(ssid, wifiInfo.bssid)\n    }\n\n    override fun localDNSTransport(): LocalDNSTransport? = LocalResolver\n\n    @OptIn(ExperimentalEncodingApi::class)\n    override fun systemCertificates(): StringIterator {\n        val certificates = mutableListOf<String>()\n        val keyStore = KeyStore.getInstance(\"AndroidCAStore\")\n        if (keyStore != null) {\n            keyStore.load(null, null)\n            val aliases = keyStore.aliases()\n            while (aliases.hasMoreElements()) {\n                val cert = keyStore.getCertificate(aliases.nextElement())\n                certificates.add(\n                    \"-----BEGIN CERTIFICATE-----\\n\" + Base64.encode(cert.encoded) + \"\\n-----END CERTIFICATE-----\",\n                )\n            }\n        }\n        return StringArray(certificates.iterator())\n    }\n\n    private class InterfaceArray(private val iterator: Iterator<LibboxNetworkInterface>) : NetworkInterfaceIterator {\n        override fun hasNext(): Boolean = iterator.hasNext()\n\n        override fun next(): LibboxNetworkInterface = iterator.next()\n    }\n\n    class StringArray(private val iterator: Iterator<String>) : StringIterator {\n        override fun len(): Int {\n            // not used by core\n            return 0\n        }\n\n        override fun hasNext(): Boolean = iterator.hasNext()\n\n        override fun next(): String = iterator.next()\n    }\n\n    private fun InterfaceAddress.toPrefix(): String = if (address is Inet6Address) {\n        \"${Inet6Address.getByAddress(address.address).hostAddress}/$networkPrefixLength\"\n    } else {\n        \"${address.hostAddress}/$networkPrefixLength\"\n    }\n\n    private val NetworkInterface.flags: Int\n        @SuppressLint(\"SoonBlockedPrivateApi\")\n        get() {\n            val getFlagsMethod = NetworkInterface::class.java.getDeclaredMethod(\"getFlags\")\n            return getFlagsMethod.invoke(this) as Int\n        }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/ProxyService.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.app.Service\nimport android.content.Intent\nimport com.hiddify.core.libbox.Notification\n\nclass ProxyService :\n    Service(),\n    PlatformInterfaceWrapper {\n    private val service = BoxService(this, this)\n\n    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int) = service.onStartCommand()\n\n    override fun onBind(intent: Intent) = service.onBind(intent)\n\n    override fun onDestroy() = service.onDestroy()\n\n    override fun sendNotification(notification: Notification) = service.sendNotification(notification)\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/ServiceBinder.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.os.RemoteCallbackList\nimport androidx.lifecycle.MutableLiveData\nimport com.hiddify.hiddify.IService\nimport com.hiddify.hiddify.IServiceCallback\nimport com.hiddify.hiddify.constant.Status\nimport kotlinx.coroutines.DelicateCoroutinesApi\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.sync.Mutex\nimport kotlinx.coroutines.sync.withLock\nclass ServiceBinder(private val status: MutableLiveData<Status>) : IService.Stub() {\n    private val callbacks = RemoteCallbackList<IServiceCallback>()\n    private val broadcastLock = Mutex()\n\n    init {\n        status.observeForever {\n            broadcast { callback ->\n                callback.onServiceStatusChanged(it.ordinal)\n            }\n        }\n    }\n\n    @OptIn(DelicateCoroutinesApi::class)\n    fun broadcast(work: (IServiceCallback) -> Unit) {\n        GlobalScope.launch(Dispatchers.Main) {\n            broadcastLock.withLock {\n                val count = callbacks.beginBroadcast()\n                try {\n                    repeat(count) {\n                        try {\n                            work(callbacks.getBroadcastItem(it))\n                        } catch (_: Exception) {\n                        }\n                    }\n                } finally {\n                    callbacks.finishBroadcast()\n                }\n            }\n        }\n    }\n\n    override fun getStatus(): Int = (status.value ?: Status.Stopped).ordinal\n\n    override fun registerCallback(callback: IServiceCallback) {\n        callbacks.register(callback)\n    }\n\n    override fun unregisterCallback(callback: IServiceCallback?) {\n        callbacks.unregister(callback)\n    }\n\n    fun close() {\n        callbacks.kill()\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/ServiceConnection.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport com.hiddify.hiddify.IService\nimport com.hiddify.hiddify.IServiceCallback\nimport com.hiddify.hiddify.Settings\nimport com.hiddify.hiddify.constant.Action\nimport com.hiddify.hiddify.constant.Alert\nimport com.hiddify.hiddify.constant.Status\nimport android.content.ComponentName\nimport android.content.Context\nimport android.content.Intent\nimport android.content.ServiceConnection\nimport android.os.IBinder\nimport android.os.RemoteException\nimport android.util.Log\nimport androidx.appcompat.app.AppCompatActivity\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.runBlocking\nimport kotlinx.coroutines.withContext\n\n\nclass ServiceConnection(private val context: Context, callback: Callback, private val register: Boolean = true) : ServiceConnection {\n    companion object {\n        private const val TAG = \"ServiceConnection\"\n    }\n\n    private val callback = ServiceCallback(callback)\n    private var service: IService? = null\n\n    val status get() = service?.status?.let { Status.values()[it] } ?: Status.Stopped\n\n    fun connect() {\n        val intent =\n            runBlocking {\n                withContext(Dispatchers.IO) {\n                    Intent(context, Settings.serviceClass()).setAction(Action.SERVICE)\n                }\n            }\n        context.bindService(intent, this, AppCompatActivity.BIND_AUTO_CREATE)\n        Log.d(TAG, \"request connect\")\n    }\n\n    fun disconnect() {\n        try {\n            context.unbindService(this)\n        } catch (_: IllegalArgumentException) {\n        }\n        Log.d(TAG, \"request disconnect\")\n    }\n\n    fun reconnect() {\n        try {\n            context.unbindService(this)\n        } catch (_: IllegalArgumentException) {\n        }\n        val intent =\n            runBlocking {\n                withContext(Dispatchers.IO) {\n                    Intent(context, Settings.serviceClass()).setAction(Action.SERVICE)\n                }\n            }\n        context.bindService(intent, this, AppCompatActivity.BIND_AUTO_CREATE)\n        Log.d(TAG, \"request reconnect\")\n    }\n\n    override fun onServiceConnected(name: ComponentName, binder: IBinder) {\n        val service = IService.Stub.asInterface(binder)\n        this.service = service\n        try {\n            if (register) service.registerCallback(callback)\n            callback.onServiceStatusChanged(service.status)\n        } catch (e: RemoteException) {\n            Log.e(TAG, \"initialize service connection\", e)\n        }\n        Log.d(TAG, \"service connected\")\n    }\n\n    override fun onServiceDisconnected(name: ComponentName?) {\n        try {\n            service?.unregisterCallback(callback)\n        } catch (e: RemoteException) {\n            Log.e(TAG, \"cleanup service connection\", e)\n        }\n        Log.d(TAG, \"service disconnected\")\n    }\n\n    override fun onBindingDied(name: ComponentName?) {\n        reconnect()\n        Log.d(TAG, \"service dead\")\n    }\n\n    interface Callback {\n        fun onServiceStatusChanged(status: Status)\n\n        fun onServiceAlert(type: Alert, message: String?) {\n        }\n    }\n\n    class ServiceCallback(private val callback: Callback) : IServiceCallback.Stub() {\n        override fun onServiceStatusChanged(status: Int) {\n            callback.onServiceStatusChanged(Status.values()[status])\n        }\n\n        override fun onServiceAlert(type: Int, message: String?) {\n            callback.onServiceAlert(Alert.values()[type], message)\n        }\n\n        override fun onServiceWriteLog(message: String?) {\n            //TODO(\"Not yet implemented\")\n        }\n\n        override fun onServiceResetLogs(messages: List<String?>?) {\n            //TODO(\"Not yet implemented\")\n        }\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/ServiceNotification.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.app.NotificationChannel\nimport android.app.NotificationManager\nimport android.app.PendingIntent\nimport android.app.Service\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport android.content.IntentFilter\nimport android.os.Build\nimport android.util.Log\nimport androidx.annotation.StringRes\nimport androidx.core.app.NotificationCompat\nimport androidx.core.app.ServiceCompat\nimport androidx.lifecycle.MutableLiveData\nimport com.hiddify.core.api.v2.config.Protocol\nimport com.hiddify.core.api.v2.hcommon.Empty\nimport com.hiddify.core.api.v2.hcore.CoreClient\nimport com.hiddify.core.api.v2.hcore.SystemInfo\nimport com.hiddify.core.api.v2.hello.HelloClient\nimport com.hiddify.core.api.v2.hello.HelloRequest\nimport com.hiddify.hiddify.Application\nimport com.hiddify.hiddify.MainActivity\nimport com.hiddify.hiddify.R\nimport com.hiddify.hiddify.Settings\nimport com.hiddify.hiddify.constant.Action\nimport com.hiddify.hiddify.constant.Status\n//import com.hiddify.hiddify.utils.CommandClient\nimport com.hiddify.core.libbox.Libbox\nimport com.hiddify.hiddify.Application.Companion.notification\nimport com.hiddify.hiddify.utils.GrpcClientProvider\nimport com.squareup.wire.GrpcClient\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.isActive\n\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.SupervisorJob\nimport kotlinx.coroutines.channels.ReceiveChannel\nimport kotlinx.coroutines.channels.SendChannel\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport okhttp3.OkHttpClient\nimport java.io.IOException\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.CancellationException\nclass ServiceNotification(private val status: MutableLiveData<Status>, private val service: Service) : BroadcastReceiver(){\n    companion object {\n        private const val notificationId = 1\n        private const val notificationChannel = \"service\"\n        var coreClient: CoreClient?=null\n        val flags =\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0\n\n        fun checkPermission(): Boolean {\n            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {\n                return true\n            }\n            return Application.notification.areNotificationsEnabled()\n        }\n    }\n    val streamingCoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())\n\n\n//\n//    private val commandClient =\n//            CommandClient(GlobalScope, CommandClient.ConnectionType.Status, this)\n    private var receiverRegistered = false\n\n\n    private val notificationBuilder by lazy {\n        NotificationCompat.Builder(service, notificationChannel)\n                .setShowWhen(false)\n                .setOngoing(true)\n                .setContentTitle(\"Hiddify\")\n                .setOnlyAlertOnce(true)\n                .setSmallIcon(R.drawable.ic_stat_logo)\n                .setCategory(NotificationCompat.CATEGORY_SERVICE)\n                .setContentIntent(\n                        PendingIntent.getActivity(\n                                service,\n                                0,\n                                Intent(\n                                        service,\n                                        MainActivity::class.java\n                                ).setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT),\n                                flags\n                        )\n                )\n                .setPriority(NotificationCompat.PRIORITY_LOW).apply {\n                    addAction(\n                            NotificationCompat.Action.Builder(\n                                    0, service.getText(R.string.stop), PendingIntent.getBroadcast(\n                                    service,\n                                    0,\n                                    Intent(Action.SERVICE_CLOSE).setPackage(\n                                        Application.application.packageName\n                                    ),\n                                    flags\n                            )\n                            ).build()\n                    )\n                }\n    }\n\n    fun show(profileName: String, @StringRes contentTextId: Int) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n            Application.notification.createNotificationChannel(\n                NotificationChannel(\n                    notificationChannel, \"hiddify service\", NotificationManager.IMPORTANCE_LOW\n                )\n            )\n        }\n        service.startForeground(\n            notificationId, notificationBuilder\n                .setContentTitle(profileName.takeIf { it.isNotBlank() } ?: \"Hiddify\")\n                .setContentText(service.getString(contentTextId)).build()\n        )\n    }\n\n\n    suspend fun start() {\n        if (Settings.dynamicNotification && checkPermission()) {\n//            commandClient.connect()\n            startListenSystemInfo()\n            withContext(Dispatchers.Main) {\n                registerReceiver()\n            }\n        }\n    }\n\n    private fun registerReceiver() {\n        service.registerReceiver(this, IntentFilter().apply {\n            addAction(Intent.ACTION_SCREEN_ON)\n            addAction(Intent.ACTION_SCREEN_OFF)\n        })\n        receiverRegistered = true\n    }\n\n    fun updateStatus(previous:SystemInfo,status: SystemInfo) {\n        val uplink=status.uplink_total - previous.uplink_total\n        val downlink=status.downlink_total - previous.downlink_total\n        val content = \"${Libbox.formatBytes(uplink)}/s ↑\\t${Libbox.formatBytes(downlink)}/s ↓ \\n${status.current_outbound}\"\n        val title = \"${status.current_profile}\"\n        Application.notificationManager.notify(\n                notificationId,\n                notificationBuilder.setContentTitle(title).setContentText(content).build()\n        )\n    }\n\n    override fun onReceive(context: Context, intent: Intent) {\n        when (intent.action) {\n            Intent.ACTION_SCREEN_ON -> {\n                startListenSystemInfo()\n            }\n\n            Intent.ACTION_SCREEN_OFF -> {\n                stopListenSystemInfo()\n            }\n        }\n    }\n\n    fun close() {\n        stopListenSystemInfo()\n        ServiceCompat.stopForeground(service, ServiceCompat.STOP_FOREGROUND_REMOVE)\n        if (receiverRegistered) {\n            service.unregisterReceiver(this)\n            receiverRegistered = false\n        }\n    }\n\n    private var streamingJob: Job? = null\n\n    fun startListenSystemInfo() {\n        // Cancel any previous stream if still running\n        Log.d(\"notification\",\"startListenSystemInfo\")\n        streamingJob?.cancel()\n\n        streamingJob = streamingCoroutineScope.launch(Dispatchers.IO) {\n            Log.d(\"notification\", \"startListenSystemInfo-launch\")\n\n            val coreClient = GrpcClientProvider.grpcClient.create(CoreClient::class)\n\n            try {\n                var previous = coreClient.GetSystemInfo().executeBlocking(Empty())\n\n                while (isActive) {\n                    delay(1_000) // ✅ coroutine-friendly\n                    val current = coreClient.GetSystemInfo().executeBlocking(Empty())\n                    updateStatus(previous,current)\n                    previous = current\n                }\n            } catch (e: CancellationException) {\n                // coroutine cancelled normally\n                Log.d(\"notification\", \"SystemInfo polling cancelled\")\n                notification.cancel(notificationId)\n            } catch (e: Exception) {\n                Log.e(\"notification\", \"SystemInfo polling failed\", e)\n                notification.cancel(notificationId)\n            }\n        }\n    }\n    fun stopListenSystemInfo(){\n        try {\n            streamingJob?.cancel()\n        }catch (e: Exception){\n            Log.d(\"notification\", \"Exception ${e}\")\n        }\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/TileService.kt",
    "content": "package com.hiddify.hiddify.bg\n\nimport android.app.KeyguardManager\nimport android.content.Context\nimport android.content.Intent\nimport android.service.quicksettings.Tile\nimport android.service.quicksettings.TileService\nimport android.util.Log\nimport androidx.annotation.RequiresApi\nimport androidx.core.content.ContextCompat\nimport androidx.lifecycle.lifecycleScope\nimport com.hiddify.hiddify.Application\nimport com.hiddify.hiddify.MainActivity\nimport com.hiddify.hiddify.Settings\nimport com.hiddify.hiddify.constant.ServiceMode\nimport com.hiddify.hiddify.constant.Status\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\n@RequiresApi(24)\nclass TileService : TileService(), ServiceConnection.Callback {\n\n    private val connection = ServiceConnection(this, this)\n\n    override fun onServiceStatusChanged(status: Status) {\n        qsTile?.apply {\n            state =\n                when (status) {\n                    Status.Started -> Tile.STATE_ACTIVE\n                    Status.Stopped -> Tile.STATE_INACTIVE\n                    else -> Tile.STATE_UNAVAILABLE\n                }\n            updateTile()\n        }\n    }\n\n    override fun onStartListening() {\n        super.onStartListening()\n        connection.connect()\n    }\n\n    override fun onStopListening() {\n        connection.disconnect()\n        super.onStopListening()\n    }\n    private fun toggleService() {\n        when (connection.status) {\n            Status.Stopped -> {\n                Settings.startCoreAfterStartingService = true\n                BoxService.start()\n                qsTile?.apply {\n                    state = Tile.STATE_ACTIVE\n                    updateTile()\n                }\n            }\n            Status.Started -> {\n                BoxService.stop()\n                qsTile?.apply {\n                    state = Tile.STATE_INACTIVE\n                    updateTile()\n                }\n            }\n            else -> {}\n        }\n    }\n\n    override fun onClick() {\n        val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager\n        if (keyguardManager.isKeyguardLocked) {\n            unlockAndRun {\n                toggleService()\n            }\n        } else {\n            toggleService()\n        }\n    }\n\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/bg/VPNService.kt",
    "content": "package com.hiddify.hiddify.bg\nimport android.util.Log\n\nimport com.hiddify.hiddify.Settings\nimport android.content.Intent\nimport android.content.pm.PackageManager.NameNotFoundException\nimport android.net.ProxyInfo\nimport android.net.VpnService\nimport android.os.Build\nimport android.os.IBinder\nimport android.os.ParcelFileDescriptor\nimport com.hiddify.core.libbox.Notification\nimport com.hiddify.hiddify.constant.PerAppProxyMode\nimport com.hiddify.hiddify.ktx.toIpPrefix\nimport com.hiddify.core.libbox.TunOptions\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.runBlocking\nimport kotlinx.coroutines.withContext\n\nclass VPNService : VpnService(), PlatformInterfaceWrapper {\n\n    companion object {\n        private const val TAG = \"A/VPNService\"\n    }\n\n    private val service = BoxService(this, this)\n\n    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int) =\n        service.onStartCommand()\n\n    override fun onBind(intent: Intent): IBinder {\n        val binder = super.onBind(intent)\n        if (binder != null) {\n            return binder\n        }\n        return service.onBind(intent)\n    }\n\n    override fun onDestroy() {\n        service.onDestroy()\n    }\n\n    override fun onRevoke() {\n        runBlocking {\n            withContext(Dispatchers.Main) {\n                service.onRevoke()\n            }\n        }\n    }\n\n    override fun autoDetectInterfaceControl(fd: Int) {\n        protect(fd)\n    }\n\n    var systemProxyAvailable = false\n    var systemProxyEnabled = false\n    fun addIncludePackage(builder: Builder, packageName: String) {\n        if (packageName == this.packageName) { \n            Log.d(\"VpnService\",\"Cannot include myself: $packageName\")\n            return\n        }\n        try {     \n            Log.d(\"VpnService\",\"Including $packageName\")\n            builder.addAllowedApplication(packageName)\n        } catch (e: NameNotFoundException) {\n        }\n    }\n\n    fun addExcludePackage(builder: Builder, packageName: String) {\n        try {     \n            Log.d(\"VpnService\",\"Excluding $packageName\")\n            builder.addDisallowedApplication(packageName)\n        } catch (e: NameNotFoundException) {\n        }\n    }\n\n    override fun openTun(options: TunOptions): Int {\n        var hasPermission = false\n        for (i in 0 until 20) {\n            if (prepare(this) != null) {\n                Log.w(\"VPN\", \"android: missing vpn permission\")\n            } else {\n                hasPermission = true\n                break\n            }\n            Thread.sleep(50)\n        }\n\n        if (!hasPermission) {\n             error(\"android: missing vpn permission\")\n    }\n//        service.fileDescriptor?.close()\n\n        val builder = Builder()\n            .setSession(\"hiddify\")\n            .setMtu(options.mtu)\n\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {\n            builder.setMetered(false)\n        }\n\n        val inet4Address = options.inet4Address\n        while (inet4Address.hasNext()) {\n            val address = inet4Address.next()\n            builder.addAddress(address.address(), address.prefix())\n        }\n\n        val inet6Address = options.inet6Address\n        while (inet6Address.hasNext()) {\n            val address = inet6Address.next()\n            builder.addAddress(address.address(), address.prefix())\n        }\n\n        if (options.autoRoute) {\n            builder.addDnsServer(options.dnsServerAddress.value)\n\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {\n                val inet4RouteAddress = options.inet4RouteAddress\n                if (inet4RouteAddress.hasNext()) {\n                    while (inet4RouteAddress.hasNext()) {\n                        builder.addRoute(inet4RouteAddress.next().toIpPrefix())\n                    }\n                } else {\n                    builder.addRoute(\"0.0.0.0\", 0)\n                }\n\n                val inet6RouteAddress = options.inet6RouteAddress\n                if (inet6RouteAddress.hasNext()) {\n                    while (inet6RouteAddress.hasNext()) {\n                        builder.addRoute(inet6RouteAddress.next().toIpPrefix())\n                    }\n                } else {\n                    builder.addRoute(\"::\", 0)\n                }\n\n                val inet4RouteExcludeAddress = options.inet4RouteExcludeAddress\n                while (inet4RouteExcludeAddress.hasNext()) {\n                    builder.excludeRoute(inet4RouteExcludeAddress.next().toIpPrefix())\n                }\n\n                val inet6RouteExcludeAddress = options.inet6RouteExcludeAddress\n                while (inet6RouteExcludeAddress.hasNext()) {\n                    builder.excludeRoute(inet6RouteExcludeAddress.next().toIpPrefix())\n                }\n            } else {\n                val inet4RouteAddress = options.inet4RouteRange\n                if (inet4RouteAddress.hasNext()) {\n                    while (inet4RouteAddress.hasNext()) {\n                        val address = inet4RouteAddress.next()\n                        builder.addRoute(address.address(), address.prefix())\n                    }\n                }\n\n                val inet6RouteAddress = options.inet6RouteRange\n                if (inet6RouteAddress.hasNext()) {\n                    while (inet6RouteAddress.hasNext()) {\n                        val address = inet6RouteAddress.next()\n                        builder.addRoute(address.address(), address.prefix())\n                    }\n                }\n            }\n\n            if (Settings.perAppProxyEnabled) {\n                val appList = Settings.perAppProxyList\n                if (Settings.perAppProxyMode == PerAppProxyMode.INCLUDE) {\n                    appList.forEach {\n                        addIncludePackage(builder,it)\n                    }\n//                    addIncludePackage(builder,packageName)\n                } else {\n                    appList.forEach {\n                        addExcludePackage(builder,it)\n                    }\n                    addExcludePackage(builder,packageName)\n                }\n            } else {\n                val includePackage = options.includePackage\n                if (includePackage.hasNext()) {\n                    while (includePackage.hasNext()) {\n                        addIncludePackage(builder,includePackage.next())\n                    }\n                    //                    addIncludePackage(builder,packageName)\n                }else {\n                    val excludePackage = options.excludePackage\n                    if (excludePackage.hasNext()) {\n                        while (excludePackage.hasNext()) {\n                            addExcludePackage(builder, excludePackage.next())\n                        }\n                    }\n\n                    addExcludePackage(builder, packageName)\n                }\n                \n            }\n        }\n\n        if (options.isHTTPProxyEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {\n            systemProxyAvailable = true\n            systemProxyEnabled = Settings.systemProxyEnabled\n            if (systemProxyEnabled) builder.setHttpProxy(\n                ProxyInfo.buildDirectProxy(\n                    options.httpProxyServer, options.httpProxyServerPort\n                )\n            )\n        } else {\n            systemProxyAvailable = false\n            systemProxyEnabled = false\n        }\n\n        val pfd = builder.establish() ?: error(\"android: the application is not prepared or is revoked\")\n        service.fileDescriptor = pfd\n        return pfd.fd\n    }\n\n//    override fun writeLog(message: String) = service.writeLog(message)\n\n    override fun sendNotification(notification: Notification) {\n//        service.sendNotification(notification)\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/constant/Action.kt",
    "content": "package com.hiddify.hiddify.constant\n\nobject Action {\n    const val SERVICE = \"com.hiddify.app.SERVICE\"\n    const val SERVICE_CLOSE = \"com.hiddify.app.SERVICE_CLOSE\"\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/constant/Alert.kt",
    "content": "package com.hiddify.hiddify.constant\n\nenum class Alert {\n    RequestVPNPermission,\n    RequestNotificationPermission,\n    EmptyConfiguration,\n    StartCommandServer,\n    CreateService,\n    StartService\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/constant/PerAppProxyMode.kt",
    "content": "package com.hiddify.hiddify.constant\n\nobject PerAppProxyMode {\n    const val OFF = \"off\"\n    const val INCLUDE = \"include\"\n    const val EXCLUDE = \"exclude\"\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/constant/ServiceMode.kt",
    "content": "package com.hiddify.hiddify.constant\n\nobject ServiceMode {\n    const val NORMAL = \"proxy\"\n    const val VPN = \"vpn\"\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/constant/SettingsKey.kt",
    "content": "package com.hiddify.hiddify.constant\n\nobject SettingsKey {\n    private const val KEY_PREFIX = \"flutter.\"\n\n    const val SERVICE_MODE = \"${KEY_PREFIX}service-mode\"\n    const val ACTIVE_CONFIG_PATH = \"${KEY_PREFIX}active_config_path\"\n    const val ACTIVE_PROFILE_NAME = \"${KEY_PREFIX}active_profile_name\"\n\n    const val PER_APP_PROXY_MODE = \"${KEY_PREFIX}per_app_proxy_mode\"\n    const val PER_APP_PROXY_INCLUDE_LIST = \"${KEY_PREFIX}per_app_proxy_include_list\"\n    const val PER_APP_PROXY_EXCLUDE_LIST = \"${KEY_PREFIX}per_app_proxy_exclude_list\"\n\n    const val DEBUG_MODE = \"${KEY_PREFIX}debug_mode\"\n    const val DISABLE_MEMORY_LIMIT = \"${KEY_PREFIX}disable_memory_limit\"\n    const val DYNAMIC_NOTIFICATION = \"${KEY_PREFIX}dynamic_notification\"\n    const val SYSTEM_PROXY_ENABLED = \"${KEY_PREFIX}system_proxy_enabled\"\n\n    // cache\n\n    const val STARTED_BY_USER = \"${KEY_PREFIX}started_by_user\"\n    const val CONFIG_OPTIONS = \"config_options_json\"\n\n    const val START_CORE_ON_STARTING_SERVICE = \"${KEY_PREFIX}starting_core_on_starting_service\"\n\n    const val WORKING_DIR = \"working_dir\"\n    const val BASE_DIR = \"base_dir\"\n    const val TMP_DIR = \"tmp_dir\"\n\n    const val GRPC_PORT = \"grpc_port\"\n    const val GRPC_FLUTTER_PUBLIC_KEY = \"grpc_flutter_public_key\"\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/constant/Status.kt",
    "content": "package com.hiddify.hiddify.constant\n\nenum class Status {\n    Stopped,\n    Starting,\n    Started,\n    Stopping,\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/constant/bugs.kt",
    "content": "package com.hiddify.hiddify.constant\n\n\nimport android.os.Build\nimport com.hiddify.hiddify.BuildConfig\n\n\nobject Bugs {\n\n    // TODO: remove launch after fixed\n    // https://github.com/golang/go/issues/68760\n    val fixAndroidStack = BuildConfig.DEBUG ||\n            Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 ||\n            Build.VERSION.SDK_INT >= Build.VERSION_CODES.P\n\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/ktx/Continuations.kt",
    "content": "package com.hiddify.hiddify.ktx\n\nimport kotlin.coroutines.Continuation\n\n\nfun <T> Continuation<T>.tryResume(value: T) {\n    try {\n        resumeWith(Result.success(value))\n    } catch (ignored: IllegalStateException) {\n    }\n}\n\nfun <T> Continuation<T>.tryResumeWithException(exception: Throwable) {\n    try {\n        resumeWith(Result.failure(exception))\n    } catch (ignored: IllegalStateException) {\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/ktx/Wrappers.kt",
    "content": "package com.hiddify.hiddify.ktx\n\nimport android.net.IpPrefix\nimport android.os.Build\nimport androidx.annotation.RequiresApi\nimport com.hiddify.core.libbox.RoutePrefix\nimport com.hiddify.core.libbox.StringIterator\nimport com.hiddify.core.libbox.StringBox\nimport java.net.InetAddress\n\nval StringBox?.unwrap: String\nget() {\n    if (this == null) return \"\"\n    return value\n}\n\nfun StringIterator.toList(): List<String> {\n    return mutableListOf<String>().apply {\n        while (hasNext()) {\n            add(next())\n        }\n    }\n}\n\n@RequiresApi(Build.VERSION_CODES.TIRAMISU)\nfun RoutePrefix.toIpPrefix() = IpPrefix(InetAddress.getByName(address()), prefix())"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/utils/CommandClient.kt",
    "content": "package com.hiddify.hiddify.utils\n\nimport com.hiddify.core.libbox.CommandClient\nimport com.hiddify.core.libbox.CommandClientHandler\nimport com.hiddify.core.libbox.CommandClientOptions\nimport com.hiddify.core.libbox.Connections\nimport com.hiddify.core.libbox.Libbox\nimport com.hiddify.core.libbox.OutboundGroup\nimport com.hiddify.core.libbox.OutboundGroupIterator\nimport com.hiddify.core.libbox.StatusMessage\nimport com.hiddify.core.libbox.StringIterator\nimport com.hiddify.hiddify.ktx.toList\nimport go.Seq\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.isActive\nimport kotlinx.coroutines.launch\n\n//open class CommandClient(\n//    private val scope: CoroutineScope,\n//    private val connectionType: ConnectionType,\n//    private val handler: Handler\n//) {\n//\n//    enum class ConnectionType {\n//        Status, Groups, Log, ClashMode, GroupOnly\n//    }\n//\n//    interface Handler {\n//\n//        fun onConnected() {}\n//        fun onDisconnected() {}\n//        fun updateStatus(status: StatusMessage) {}\n//        fun updateGroups(groups: List<OutboundGroup>) {}\n//        fun clearLog() {}\n//        fun appendLog(message: String) {}\n//        fun initializeClashMode(modeList: List<String>, currentMode: String) {}\n//        fun updateClashMode(newMode: String) {}\n//\n//    }\n//\n//\n//    private var commandClient: CommandClient? = null\n//    private val clientHandler = ClientHandler()\n//    fun connect() {\n//        disconnect()\n//        val options = CommandClientOptions()\n//        options.command = when (connectionType) {\n//            ConnectionType.Status -> Libbox.CommandStatus\n//            ConnectionType.Groups -> Libbox.CommandGroup\n//            ConnectionType.Log -> Libbox.CommandLog\n//            ConnectionType.ClashMode -> Libbox.CommandClashMode\n//            ConnectionType.GroupOnly -> Libbox.CommandGroupInfoOnly\n//        }\n//        options.statusInterval = 2 * 1000 * 1000 * 1000\n//        val commandClient = CommandClient(clientHandler, options)\n//        scope.launch(Dispatchers.IO) {\n//            for (i in 1..10) {\n//                delay(100 + i.toLong() * 50)\n//                try {\n//                    commandClient.connect()\n//                } catch (ignored: Exception) {\n//                    continue\n//                }\n//                if (!isActive) {\n//                    runCatching {\n//                        commandClient.disconnect()\n//                    }\n//                    return@launch\n//                }\n//                this@CommandClient.commandClient = commandClient\n//                return@launch\n//            }\n//            runCatching {\n//                commandClient.disconnect()\n//            }\n//        }\n//    }\n//\n//    fun disconnect() {\n//        commandClient?.apply {\n//            runCatching {\n//                disconnect()\n//            }\n//            Seq.destroyRef(refnum)\n//        }\n//        commandClient = null\n//    }\n//\n//    private inner class ClientHandler : CommandClientHandler {\n//\n//        override fun connected() {\n//            handler.onConnected()\n//        }\n//\n//        override fun disconnected(message: String?) {\n//            handler.onDisconnected()\n//        }\n//\n//        override fun writeGroups(message: OutboundGroupIterator?) {\n//            if (message == null) {\n//                return\n//            }\n//            val groups = mutableListOf<OutboundGroup>()\n//            while (message.hasNext()) {\n//                groups.add(message.next())\n//            }\n//            handler.updateGroups(groups)\n//        }\n//\n//        override fun clearLogs() {\n//            handler.clearLog()\n//        }\n//        override fun writeLogs(messageList: StringIterator?) {\n//\n//            if (messageList == null) {\n//                return\n//            }\n//\n//\n//            while (messageList.hasNext()) {\n//                handler.appendLog(messageList.next())\n//            }\n//\n//        }\n//\n//        override fun writeStatus(message: StatusMessage?) {\n//            if (message == null) {\n//                return\n//            }\n//            handler.updateStatus(message)\n//        }\n//\n//        override fun initializeClashMode(modeList: StringIterator, currentMode: String) {\n//            handler.initializeClashMode(modeList.toList(), currentMode)\n//        }\n//\n//        override fun updateClashMode(newMode: String) {\n//            handler.updateClashMode(newMode)\n//        }\n//\n//\n//\n//        override fun writeConnections(message: Connections?) {\n//        }\n//\n//    }\n//\n//}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/utils/GrpcProvider.kt",
    "content": "package com.hiddify.hiddify.utils\n\n/*\n * Copyright (C) 2019 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport com.hiddify.core.api.v2.hcore.CoreClient\nimport com.hiddify.hiddify.Settings\nimport com.squareup.wire.GrpcClient\nimport io.grpc.CallOptions\nimport io.grpc.ManagedChannelBuilder\nimport java.io.IOException\nimport java.io.InputStream\nimport java.security.GeneralSecurityException\nimport java.security.KeyStore\nimport java.security.cert.CertificateFactory\nimport java.time.Duration\nimport java.util.Arrays\nimport javax.net.ssl.KeyManagerFactory\nimport javax.net.ssl.SSLContext\nimport javax.net.ssl.SSLSocketFactory\nimport javax.net.ssl.TrustManagerFactory\nimport javax.net.ssl.X509TrustManager\nimport okhttp3.OkHttpClient\nimport okhttp3.Protocol\nimport okhttp3.Protocol.HTTP_1_1\nimport okhttp3.Protocol.HTTP_2\nimport okio.Buffer\nimport java.util.concurrent.TimeUnit\n\nobject GrpcClientProvider {\n    private val okHttpClient = OkHttpClient.Builder()\n        .protocols(listOf(Protocol.H2_PRIOR_KNOWLEDGE))\n        .connectTimeout(10, TimeUnit.SECONDS)\n        .readTimeout(10, TimeUnit.SECONDS)\n        .writeTimeout(10, TimeUnit.SECONDS)\n        .build()\n\n    val grpcClient: GrpcClient = GrpcClient.Builder()\n        .client(okHttpClient)\n        .baseUrl(\"http://127.0.0.1:${Settings.grpcServiceModePort}\")\n        .build()\n\n\n    private fun socketFactoryAndTrustManager(): Pair<SSLSocketFactory, X509TrustManager> {\n        val trustManager: X509TrustManager\n        val sslSocketFactory: SSLSocketFactory\n        try {\n            trustManager = trustManagerForCertificates(\n                trustedCertificatesInputStream(),\n            )\n            val sslContext = SSLContext.getInstance(\"TLS\")\n            sslContext.init(null, arrayOf(trustManager), null)\n            sslSocketFactory = sslContext.socketFactory\n        } catch (e: GeneralSecurityException) {\n            throw RuntimeException(e)\n        }\n\n        return sslSocketFactory to trustManager\n    }\n\n    private fun trustedCertificatesInputStream(): InputStream {\n        val myCertificate = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIC/DCCAeSgAwIBAgIBATANBgkqhkiG9w0BAQsFADAvMS0wKwYDVQQDEyRkNWY2\\n\" +\n                \"NTRhNC0zOWJlLTQyYjEtOGNlYi1kYTI3MmJmNTI2ZTQwIBcNMTkwODEyMjEwMzIx\\n\" +\n                \"WhgPMjExOTA3MTkyMTAzMjFaMC8xLTArBgNVBAMTJGQ1ZjY1NGE0LTM5YmUtNDJi\\n\" +\n                \"MS04Y2ViLWRhMjcyYmY1MjZlNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\\n\" +\n                \"ggEBAJQzrBa2Zp7lJ8vJ/EWrkGU2BAOublkMl5XI0cbSIfbvuITXgHX7W5sDeEwx\\n\" +\n                \"6ultnUBVg6PmEbLAaZFtqg7gFPaVGbvP4h07FHSjRdf+y8W3QgoBIhc7/zuJiw1h\\n\" +\n                \"CsJ9D7eGl2dnXO6FgdY6ISnPAfxzzrZPCJtKL+Ffm9UnfCA7AYaQQZoymqVTGIsC\\n\" +\n                \"QAekkRkRia7gpUrTvR0hXST18KMcB7QKEv75rL8pEPHirJjyujBh+4VYVpLRDtbc\\n\" +\n                \"QKxCCXcn/zhTsn+4TV/4SgO1IhU+TBv4/iffzLi/aXKEEoPJhgIbMOd5ri1XBsTe\\n\" +\n                \"pGNaBOlYlEm8q8u1E3nGxzmkBtMCAwEAAaMhMB8wHQYDVR0RAQH/BBMwEYIJbG9j\\n\" +\n                \"YWxob3N0hwQKAAICMA0GCSqGSIb3DQEBCwUAA4IBAQAjL/inUHQbYD6bosFDQfyL\\n\" +\n                \"E9LOanO3ewiuZr5Sa4DJ5n8kNPdAO9M9urfmTbOUdvMfrH+fqiEwo6a7NTqT9bGk\\n\" +\n                \"Ewz7/LdpvWIGMpnijLEPTDTur2VmjpjqtawvzbFiHhdzOZk3o6bKbY3qac7CxaaO\\n\" +\n                \"MWZKF+o+YRCXVAJ2NQZLW2D9ee1qOXpK7VA360MFoyfo3cP8z6DDdNJm6gDAK+wI\\n\" +\n                \"1pMCdrdwHuu+ExKKA8za4r6dThVQu5jp6d7GO+2qf9rGkm1idIgjGtsgC+hPmhLb\\n\" +\n                \"7RK0ynU3Ai32elqwTDpD1WGuP2yacSWweh3GG6lG1NNY7n3tsccUWnsZztQ66Oh4\\n\" +\n                \"-----END CERTIFICATE-----\"\n        return Buffer()\n            .writeUtf8(myCertificate)\n            .inputStream()\n    }\n\n    @Throws(GeneralSecurityException::class)\n    private fun trustManagerForCertificates(inputStream: InputStream): X509TrustManager {\n        val certificateFactory = CertificateFactory.getInstance(\"X.509\")\n        val certificates = certificateFactory.generateCertificates(inputStream)\n        if (certificates.isEmpty()) {\n            throw IllegalArgumentException(\"expected non-empty set of trusted certificates\")\n        }\n\n        // Put the certificates a key store.\n        val password = \"password\".toCharArray() // Any password will work.\n        val keyStore = newEmptyKeyStore(password)\n        for ((index, certificate) in certificates.withIndex()) {\n            val certificateAlias = index.toString()\n            keyStore.setCertificateEntry(certificateAlias, certificate)\n        }\n\n        // Use it to build an X509 trust manager.\n        val keyManagerFactory = KeyManagerFactory.getInstance(\n            KeyManagerFactory.getDefaultAlgorithm(),\n        )\n        keyManagerFactory.init(keyStore, password)\n        val trustManagerFactory = TrustManagerFactory.getInstance(\n            TrustManagerFactory.getDefaultAlgorithm(),\n        )\n        trustManagerFactory.init(keyStore)\n        val trustManagers = trustManagerFactory.trustManagers\n        if (trustManagers.size != 1 || trustManagers[0] !is X509TrustManager) {\n            throw IllegalStateException(\n                \"Unexpected default trust managers:\" + Arrays.toString(trustManagers),\n            )\n        }\n        return trustManagers[0] as X509TrustManager\n    }\n\n    @Throws(GeneralSecurityException::class)\n    private fun newEmptyKeyStore(password: CharArray): KeyStore {\n        try {\n            val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())\n            val inputStream: InputStream? = null // By convention, 'null' creates an empty key store.\n            keyStore.load(inputStream, password)\n            return keyStore\n        } catch (e: IOException) {\n            throw AssertionError(e)\n        }\n    }\n}"
  },
  {
    "path": "android/app/src/main/kotlin/com/hiddify/hiddify/utils/OutboundMapper.kt",
    "content": "package com.hiddify.hiddify.utils\n\nimport com.google.gson.annotations.SerializedName\nimport com.hiddify.core.libbox.OutboundGroup\nimport com.hiddify.core.libbox.OutboundGroupItem\n\ndata class ParsedOutboundGroup(\n    @SerializedName(\"tag\") val tag: String,\n    @SerializedName(\"type\") val type: String,\n    @SerializedName(\"selected\") val selected: String,\n    @SerializedName(\"items\") val items: List<ParsedOutboundGroupItem>\n) {\n    companion object {\n        fun fromOutbound(group: OutboundGroup): ParsedOutboundGroup {\n            val outboundItems = group.items\n            val items = mutableListOf<ParsedOutboundGroupItem>()\n            while (outboundItems.hasNext()) {\n                items.add(ParsedOutboundGroupItem(outboundItems.next()))\n            }\n            return ParsedOutboundGroup(group.tag, group.type, group.selected, items)\n        }\n    }\n}\n\ndata class ParsedOutboundGroupItem(\n    @SerializedName(\"tag\") val tag: String,\n    @SerializedName(\"type\") val type: String,\n    @SerializedName(\"url-test-delay\") val urlTestDelay: Int,\n) {\n    constructor(item: OutboundGroupItem) : this(item.tag, item.type, item.urlTestDelay)\n}"
  },
  {
    "path": "android/app/src/main/protos/extension/extension.proto",
    "content": "syntax = \"proto3\";\n\nimport \"v2/hcommon/common.proto\";\n\npackage extension;\n\noption go_package = \"github.com/hiddify/hiddify-core/extension\";\noption java_package = \"com.hiddify.core.api.extension\";\nmessage ExtensionActionResult {\n  string extension_id = 1;\n  hcommon.ResponseCode code = 2;\n  string message = 3;\n}\n\nmessage ExtensionList {\n  repeated ExtensionMsg extensions = 1;\n}\n\nmessage EditExtensionRequest {\n  string extension_id = 1;\n  bool enable = 2;\n}\n\nmessage ExtensionMsg {\n  string id = 1;\n  string title = 2;\n  string description = 3;\n  bool enable = 4;\n}\n\nmessage ExtensionRequest {\n  string extension_id = 1;\n  map<string, string> data = 2;\n}\n\nmessage SendExtensionDataRequest {\n  string extension_id = 1;\n  string button=2;\n  map<string, string> data = 3;\n}\n\nmessage ExtensionResponse {\n  ExtensionResponseType type = 1;\n  string extension_id = 2;\n  string json_ui = 3;\n}\n\n\nenum ExtensionResponseType {\n  NOTHING = 0;\n  UPDATE_UI = 1;\n  SHOW_DIALOG = 2;\n  END=3;\n}\n\n\n"
  },
  {
    "path": "android/app/src/main/protos/extension/extension_service.proto",
    "content": "\n\nsyntax = \"proto3\";\n\nimport \"extension/extension.proto\";\nimport \"v2/hcommon/common.proto\";\npackage extension;\n\noption go_package = \"github.com/hiddify/hiddify-core/extension\";\noption java_package = \"com.hiddify.core.api.extension\";\nservice ExtensionHostService {\n  rpc ListExtensions (hcommon.Empty) returns (ExtensionList) {}\n  rpc Connect (ExtensionRequest) returns (stream ExtensionResponse) {}\n  rpc EditExtension (EditExtensionRequest) returns (ExtensionActionResult) {}\n  rpc SubmitForm (SendExtensionDataRequest) returns (ExtensionActionResult) {}\n  rpc Close (ExtensionRequest) returns (ExtensionActionResult) {}\n\n  rpc GetUI (ExtensionRequest) returns (ExtensionActionResult) {}\n}"
  },
  {
    "path": "android/app/src/main/protos/v2/config/route_rule.proto",
    "content": "syntax = \"proto3\";\npackage config;\noption go_package = \"github.com/hiddify/hiddify-core/v2/config\";\noption java_package = \"com.hiddify.core.api.v2.config\";\nmessage RouteRule {\n  repeated Rule rules = 1 [json_name = \"rules\"];\n}\n\nmessage Rule {\n  uint32 list_order = 1 [json_name = \"list_order\"];\n  bool enabled = 2 [json_name = \"enabled\"];\n  string name = 3 [json_name = \"name\"];\n  Outbound outbound = 4 [json_name = \"outbound\"];\n  repeated string rule_sets = 5 [json_name = \"rule_set\"];\n  repeated string package_names = 6 [json_name = \"package_name\"];\n  repeated string process_names = 7 [json_name = \"process_name\"];\n  repeated string process_paths = 8 [json_name = \"process_path\"];\n  Network network = 9 [json_name = \"network\"];\n  repeated string port_ranges = 10 [json_name = \"port_range\"];\n  repeated string source_port_ranges = 11 [json_name = \"source_port_range\"];\n  repeated Protocol protocols = 12 [json_name = \"protocol\"];\n  repeated string ip_cidrs = 13 [json_name = \"ip_cidr\"];\n  repeated string source_ip_cidrs = 14 [json_name = \"source_ip_cidr\"];\n  repeated string domains = 15 [json_name = \"domain\"];\n  repeated string domain_suffixes = 16 [json_name = \"domain_suffix\"];\n  repeated string domain_keywords = 17 [json_name = \"domain_keyword\"];\n  repeated string domain_regexes = 18 [json_name = \"domain_regex\"];\n}\n\nenum Outbound {\n  proxy = 0;\n  direct = 1;\n  direct_with_fragment = 2;\n  block = 3;\n}\n  \nenum Network {\n  all = 0;\n  tcp = 1;\n  udp = 2;\n}\n\nenum Protocol {\n  tls = 0;\n  http = 1;\n  quic = 2;\n  stun = 3;\n  dns = 4;\n  bittorrent = 5;\n}"
  },
  {
    "path": "android/app/src/main/protos/v2/hcommon/common.proto",
    "content": "syntax = \"proto3\";\n\npackage hcommon;\n\noption go_package = \"github.com/hiddify/hiddify-core/v2/hcommon\";\noption java_package = \"com.hiddify.core.api.v2.hcommon\";\nmessage Empty {\n}\n\nenum ResponseCode {\n  OK = 0;\n  FAILED = 1;\n  AUTH_NEED = 2;\n}\n\nmessage Response {\n  ResponseCode code = 1;\n  string message = 2;\n}\n\n"
  },
  {
    "path": "android/app/src/main/protos/v2/hcore/hcore.proto",
    "content": "syntax = \"proto3\";\nimport \"v2/hcommon/common.proto\";\nimport \"google/protobuf/timestamp.proto\";\n\npackage hcore;\noption go_package = \"github.com/hiddify/hiddify-core/v2/hcore\";\noption java_package = \"com.hiddify.core.api.v2.hcore\";\n\n\nenum CoreStates {\n  STOPPED = 0;\n  STARTING = 1;\n  STARTED = 2;\n  STOPPING = 3;\n}\n\nenum MessageType {\n  EMPTY=0;\n  EMPTY_CONFIGURATION = 1;\n  START_COMMAND_SERVER = 2;\n  CREATE_SERVICE = 3;\n  START_SERVICE = 4;\n  UNEXPECTED_ERROR = 5;\n  ALREADY_STARTED = 6;\n  ALREADY_STOPPED = 7;\n  INSTANCE_NOT_FOUND = 8;\n  INSTANCE_NOT_STOPPED = 9;\n  INSTANCE_NOT_STARTED = 10;\n  ERROR_BUILDING_CONFIG = 11;\n  ERROR_PARSING_CONFIG = 12;\n  ERROR_READING_CONFIG = 13;\n  ERROR_EXTENSION = 14;\n}\n\nmessage CoreInfoResponse {\n  CoreStates core_state = 1;\n  MessageType message_type = 2;\n  string message = 3;\n}\n\nmessage StartRequest {\n  string config_path = 1;\n  string config_content = 2;  // Optional if configPath is not provided.\n  bool disable_memory_limit = 3;\n  bool delay_start = 4;\n  bool enable_old_command_server = 5;\n  bool enable_raw_config = 6;\n  string config_name = 7; \n}\n\n\nenum SetupMode {\n    OLD = 0;\n    GRPC_NORMAL = 1;\n    GRPC_BACKGROUND = 2;\n    GRPC_NORMAL_INSECURE = 3;\n    GRPC_BACKGROUND_INSECURE = 4;\n}\n\nmessage CloseRequest {\n  SetupMode mode = 1;\n}\n// Define the message equivalent of SetupParameters\nmessage SetupRequest {\n    string base_path = 1;\n    string working_dir = 2;\n    string temp_dir = 3;\n    int64 flutter_status_port = 4;\n    string listen = 5;\n    string secret = 6;\n    bool debug = 7;\n    SetupMode mode = 8;\n    bool fix_android_stack = 9;\n}\n\nmessage SystemInfo {\n  int64 memory = 1;\n  int32 goroutines = 2;\n  int32 connections_in = 3;\n  int32 connections_out = 4;\n  bool traffic_available = 5;\n  int64 uplink = 6;\n  int64 downlink = 7;\n  int64 uplink_total = 8;\n  int64 downlink_total = 9;\n  string current_outbound = 10;\n  string current_profile = 11;\n}\n\nmessage OutboundInfo {\n  string tag = 1;\n  string type = 2;\n  google.protobuf.Timestamp url_test_time = 3;\n  int32 url_test_delay = 4;\n  optional IpInfo ipinfo = 5;\n  bool is_selected = 6;\n  bool is_group = 7;\n  optional string group_selected_tag=13;\n  optional string group_selected_tag_display=14;\n  bool is_secure = 8;\n  bool is_visible = 9;\n  uint32 port = 10;\n  string host = 11;\n  string tag_display = 12;\n  int64 upload = 15;\n  int64 download = 16;\n}\n\nmessage IpInfo {\n    string ip = 1 [json_name = \"ip\"];                        // The IP address.\n    string country_code = 2 [json_name = \"country_code\"];    // The country code.\n    string region = 3 [json_name = \"region\"];                // The region (optional).\n    string city = 4 [json_name = \"city\"];                    // The city (optional).\n    int32 asn = 5 [json_name = \"asn\"];                       // The Autonomous System Number (optional).\n    string org = 6 [json_name = \"org\"];                      // The organization (optional).\n    double latitude = 7 [json_name = \"latitude\"];            // The latitude (optional).\n    double longitude = 8 [json_name = \"longitude\"];          // The longitude (optional).\n    string postal_code = 9 [json_name = \"postal_code\"];      // The postal code (optional).\n}\nmessage OutboundGroup {\n  string tag = 1;\n  string type = 2;\n  string selected=3;\n  bool selectable=4;\n  bool Is_expand=5;\n  repeated OutboundInfo items = 6;\n  \n}\nmessage OutboundGroupList{\n  repeated OutboundGroup items = 1;\n}\n\nmessage WarpAccount {\n  string account_id = 1;\n  string access_token = 2;\n}\n\nmessage WarpWireguardConfig {\n  string private_key = 1 [json_name = \"private-key\"];\n  string local_address_ipv4 = 2 [json_name = \"local-address-ipv4\"];\n  string local_address_ipv6 = 3 [json_name = \"local-address-ipv6\"];\n  string peer_public_key = 4 [json_name = \"peer-public-key\"];\n  string client_id=5 [json_name = \"client-id\"];\n}\n\nmessage WarpGenerationResponse {\n  WarpAccount account = 1;\n  string log = 2;\n  WarpWireguardConfig config = 3;\n}\n\nmessage SystemProxyStatus {\n  bool available = 1;\n  bool enabled = 2;\n}\n\nmessage ParseRequest {\n  string content = 1; \n  string config_path = 2; \n  string temp_path = 3; \n  bool debug = 4;\n}\n\nmessage ParseResponse {\n  hcommon.ResponseCode response_code = 1;\n  string content = 2;  \n  string message = 3;\n}\n\nmessage ChangeHiddifySettingsRequest {\n  string hiddify_settings_json = 1;\n}\n\nmessage GenerateConfigRequest {\n  string path = 1;\n  string temp_path = 2;\n  bool debug = 3;\n}\n\nmessage GenerateConfigResponse {\n  string config_content = 1;\n}\n\n\n\nmessage SelectOutboundRequest {\n  string group_tag = 1;\n  string outbound_tag = 2;\n}\n\nmessage UrlTestRequest {\n  string tag = 1;\n}\n\nmessage GenerateWarpConfigRequest {\n  string license_key = 1;\n  string account_id = 2;\n  string access_token = 3;\n}\n\nmessage SetSystemProxyEnabledRequest {\n  bool is_enabled = 1;\n}\n\nenum LogLevel {\n  TRACE = 0; \n  DEBUG = 1;\n  INFO = 2;\n  WARNING = 3;\n  ERROR = 4;\n  FATAL = 5;\n}\nenum LogType {\n  CORE = 0;\n  SERVICE = 1;\n  CONFIG = 2;\n}\nmessage LogMessage {\n  LogLevel level = 1;\n  LogType type = 2;\n  string message = 3;\n  google.protobuf.Timestamp time = 4;\n}\n\nmessage LogRequest {\n  LogLevel level = 1;\n}\n\nmessage StopRequest{\n}\n\n\n\n\n"
  },
  {
    "path": "android/app/src/main/protos/v2/hcore/hcore_service.proto",
    "content": "syntax = \"proto3\";\nimport \"v2/hcommon/common.proto\";\npackage hcore;\n\noption go_package = \"github.com/hiddify/hiddify-core/v2/hcore\";\noption java_package = \"com.hiddify.core.api.v2.hcore\";\nimport \"v2/hcore/hcore.proto\";\n\nservice Core {\n  rpc Start (StartRequest) returns (CoreInfoResponse);\n  rpc CoreInfoListener (hcommon.Empty) returns (stream CoreInfoResponse);\n  rpc OutboundsInfo (hcommon.Empty) returns (stream OutboundGroupList);\n  rpc MainOutboundsInfo (hcommon.Empty) returns (stream OutboundGroupList);\n  rpc GetSystemInfo (hcommon.Empty) returns (SystemInfo);\n  rpc GetSystemInfoStream (hcommon.Empty) returns (stream SystemInfo);\n  rpc Setup (SetupRequest) returns (hcommon.Response);\n  rpc Parse (ParseRequest) returns (ParseResponse);\n  rpc ChangeHiddifySettings (ChangeHiddifySettingsRequest) returns (CoreInfoResponse);\n  //rpc GenerateConfig (GenerateConfigRequest) returns (GenerateConfigResponse);\n  rpc StartService (StartRequest) returns (CoreInfoResponse);\n  rpc Stop (hcommon.Empty) returns (CoreInfoResponse);\n  rpc Restart (StartRequest) returns (CoreInfoResponse);\n  rpc SelectOutbound (SelectOutboundRequest) returns (hcommon.Response);\n  rpc UrlTest (UrlTestRequest) returns (hcommon.Response);\n  rpc UrlTestActive (hcommon.Empty) returns (hcommon.Response);\n  rpc GenerateWarpConfig (GenerateWarpConfigRequest) returns (WarpGenerationResponse);\n  rpc GetSystemProxyStatus (hcommon.Empty) returns (SystemProxyStatus);\n  rpc SetSystemProxyEnabled (SetSystemProxyEnabledRequest) returns (hcommon.Response);\n  rpc LogListener (LogRequest) returns (stream LogMessage); \n  rpc Close (CloseRequest) returns (hcommon.Empty); \n}\n\n\n"
  },
  {
    "path": "android/app/src/main/protos/v2/hcore/tunnelservice/tunnel.proto",
    "content": "syntax = \"proto3\";\n\npackage tunnelservice;\n\noption go_package = \"github.com/hiddify/hiddify-core/v2/hcore/tunnelservice\";\noption java_package = \"com.hiddify.core.api.v2.tunnelservice\";\n\n\n\nmessage TunnelStartRequest {\n    bool ipv6 = 1;\n    int32 server_port = 2;\n    string server_username=3;\n    string server_password=4;\n    bool strict_route = 5;\n    bool endpoint_independent_nat = 6;\n    string stack = 7;\n}\n\nmessage TunnelResponse {\n    string message = 1;\n}\n"
  },
  {
    "path": "android/app/src/main/protos/v2/hcore/tunnelservice/tunnel_service.proto",
    "content": "syntax = \"proto3\";\nimport \"v2/hcommon/common.proto\";\npackage tunnelservice;\n\noption go_package = \"github.com/hiddify/hiddify-core/v2/hcore/tunnelservice\";\noption java_package = \"com.hiddify.core.api.v2.hcore.tunnelservice\";\nimport \"v2/hcore/tunnelservice/tunnel.proto\";\n\nservice TunnelService {\n    rpc Start(TunnelStartRequest) returns (TunnelResponse);\n    rpc Stop(hcommon.Empty) returns (TunnelResponse);\n    rpc Status(hcommon.Empty) returns (TunnelResponse);\n    rpc Exit(hcommon.Empty) returns (TunnelResponse);\n}"
  },
  {
    "path": "android/app/src/main/protos/v2/hello/hello.proto",
    "content": "syntax = \"proto3\";\n\npackage hello;\noption go_package = \"github.com/hiddify/hiddify-core/v2/hello\";\noption java_package = \"com.hiddify.core.api.v2.hello\";\nmessage HelloRequest {\n  string name = 1;\n}\n\nmessage HelloResponse {\n  string message = 1;\n}\n"
  },
  {
    "path": "android/app/src/main/protos/v2/hello/hello_service.proto",
    "content": "syntax = \"proto3\";\n\npackage hello;\noption go_package = \"github.com/hiddify/hiddify-core/v2/hello\";\noption java_package = \"com.hiddify.core.api.v2.hello\";\nimport \"v2/hello/hello.proto\";\n\nservice Hello {\n  rpc SayHello (HelloRequest) returns (HelloResponse);\n  rpc SayHelloStream (stream HelloRequest) returns (stream HelloResponse);\n}\n"
  },
  {
    "path": "android/app/src/main/protos/v2/hiddifyoptions/hiddify_options.proto",
    "content": "/**\n * This file defines various configuration options for the Hiddify application.\n */\n\nsyntax = \"proto3\";\n\npackage hiddifyoptions;\noption go_package = \"github.com/hiddify/hiddify-core/v2/hiddifyoptions\";\noption java_package = \"com.hiddify.core.api.v2.hiddifyoptions\";\n\n/**\n * HiddifyOptions defines the configuration options for the Hiddify application.\n */\nmessage HiddifyOptions {\n  bool enable_full_config = 1; // Enables full configuration options.\n  string log_level = 2; // Specifies the logging level (e.g., INFO, DEBUG).\n  string log_file = 3; // Path to the log file.\n  bool enable_clash_api = 4; // Indicates whether the Clash API is enabled.\n  uint32 clash_api_port = 5; // Port for the Clash API (using uint32 for compatibility).\n  string web_secret = 6; // Secret key for accessing the Clash API.\n  string region = 7; // Region for the application.\n  bool block_ads = 8; // If true, blocks ads.\n  bool use_xray_core_when_possible = 9; // If true, use XRay core when possible.\n  repeated Rule rules = 10; // List of routing rules for traffic management.\n  WarpOptions warp = 11; // Configuration options for Warp.\n  WarpOptions warp2 = 12; // Additional configuration options for a second Warp instance.\n  MuxOptions mux = 13; // Configuration options for multiplexing.\n  TLSTricks tls_tricks = 14; // Options for TLS tricks.\n  DNSOptions dns_options = 15; // DNS-related options.\n  InboundOptions inbound_options = 16; // Inbound connection options.\n  URLTestOptions url_test_options = 17; // URL test configuration options.\n  RouteOptions route_options = 18; // Routing-related options.\n}\n\n/**\n * DomainStrategy defines the strategies for IP address preference when resolving domain names.\n */\nenum DomainStrategy {\n  as_is =0; // As it is.\n  prefer_ipv4 = 1; // Prefer IPv4 addresses.\n  prefer_ipv6 = 2; // Prefer IPv6 addresses.\n  ipv4_only = 3; // Only use IPv4 addresses.\n  ipv6_only = 4; // Only use IPv6 addresses.\n}\n\n/**\n * IntRange defines a range of integers for various configurations.\n * It includes the starting and ending values of the range.\n */\nmessage IntRange {\n  int32 from = 1; // Starting value of the range.\n  int32 to = 2; // Ending value of the range.\n}\n\n/**\n * DNSOptions defines DNS-related configuration options.\n */\nmessage DNSOptions {\n  string remote_dns_address = 1; // Remote DNS server address.\n  DomainStrategy remote_dns_domain_strategy = 2; // Strategy for resolving domains with remote DNS.\n  string direct_dns_address = 3; // Direct DNS server address.\n  DomainStrategy direct_dns_domain_strategy = 4; // Strategy for resolving domains with direct DNS.\n  bool independent_dns_cache = 5; // If true, enables independent DNS caching.\n  bool enable_fake_dns = 6; // If true, enables fake DNS responses.\n  bool enable_dns_routing = 7; // If true, enables DNS routing.\n}\n\n/**\n * InboundOptions defines the configuration options for inbound connections.\n */\nmessage InboundOptions {\n  bool enable_tun = 1; // If true, enables TUN interface.\n  bool enable_tun_service = 2; // If true, enables TUN service.\n  bool set_system_proxy = 3; // If true, sets the system proxy.\n  uint32 mixed_port = 4; // Port for mixed traffic (using uint32 for compatibility).\n  uint32 tproxy_port = 5; // Port for TProxy connections (using uint32 for compatibility).\n  uint32 redirect_port = 10; // Port for TProxy connections (using uint32 for compatibility).\n  uint32 direct_port = 6; // Port for local DNS service (using uint32 for compatibility).\n  uint32 mtu = 7; // Maximum Transmission Unit size (using uint32 for compatibility).\n  bool strict_route = 8; // If true, enforces strict routing.\n  string tun_stack = 9; // Specifies the TUN stack to use.\n}\n\n/**\n * URLTestOptions defines the configuration options for URL testing.\n */\nmessage URLTestOptions {\n  string connection_test_url = 1; // URL used for connection testing.\n  int64 url_test_interval = 2; // Interval for URL tests in milliseconds.\n}\n\n/**\n * RouteOptions defines options related to traffic routing.\n */\nmessage RouteOptions {\n  bool resolve_destination = 1; // If true, resolves the destination address.\n  DomainStrategy ipv6_mode = 2; // Strategy for handling IPv6 addresses.\n  bool bypass_lan = 3; // If true, bypasses LAN connections.\n  bool allow_connection_from_lan = 4; // If true, allows connections from LAN.\n}\n\n/**\n * TLSTricks defines options for TLS tricks to obfuscate traffic.\n */\nmessage TLSTricks {\n  bool enable_fragment = 1; // If true, enables fragmentation of packets.\n  IntRange fragment_size = 2; // Size of fragments to be used.\n  IntRange fragment_sleep = 3; // Sleep time between fragments.\n  bool mixed_sni_case = 4; // If true, enables mixed SNI case for obfuscation.\n  bool enable_padding = 5; // If true, enables padding of packets.\n  IntRange padding_size = 6; // Size of padding to be used.\n}\n\n/**\n * MuxOptions defines options for multiplexing connections.\n */\nmessage MuxOptions {\n  bool enable = 1; // If true, enables multiplexing.\n  bool padding = 2; // If true, enables padding for multiplexed connections.\n  int32 max_streams = 3; // Maximum number of streams allowed (using int32).\n  string protocol = 4; // Protocol used for multiplexing.\n}\n\n/**\n * WarpOptions defines configuration options for Warp.\n */\nmessage WarpOptions {\n  string id = 1; // Unique identifier for the Warp configuration.\n  bool enable_warp = 2; // If true, enables Warp functionality.\n  string mode = 3; // Operating mode for Warp.\n  WarpWireguardConfig wireguard_config = 5; // Configuration for WireGuard (defined elsewhere).\n  string fake_packets = 6; // Fake packet configuration.\n  IntRange fake_packet_size = 7; // Size of fake packets.\n  IntRange fake_packet_delay = 8; // Delay for sending fake packets.\n  string fake_packet_mode = 9; // Mode for sending fake packets.\n  string clean_ip = 10; // Clean IP address to use.\n  uint32 clean_port = 11; // Port for clean traffic (using uint32 for compatibility).\n  WarpAccount account = 12; // Account details for Warp (defined elsewhere).\n}\n\n/**\n * WarpAccount defines account details for Warp.\n */\nmessage WarpAccount {\n  string account_id = 1; // Unique account identifier.\n  string access_token = 2; // Access token for the account.\n}\n\n/**\n * WarpWireguardConfig defines the configuration details for WireGuard.\n */\nmessage WarpWireguardConfig {\n  string private_key = 1; // Private key for WireGuard.\n  string local_address_ipv4 = 2; // Local IPv4 address for WireGuard.\n  string local_address_ipv6 = 3; // Local IPv6 address for WireGuard.\n  string peer_public_key = 4; // Peer public key for WireGuard.\n  string client_id = 5; // Client identifier for WireGuard.\n}\n\n/**\n * Rule defines routing rules for managing traffic.\n */\nmessage Rule {\n  string rule_set_url = 1; // URL of the rule set.\n  string domains = 2;       // List of domains affected by this rule.\n  string ip = 3;            // IP address associated with this rule.\n  string port = 4;          // Port number associated with this rule.\n  string network = 5;       // Network type (e.g., IPv4, IPv6).\n  string protocol = 6;      // Protocol type (e.g., TCP, UDP).\n  string outbound = 7;      // Outbound traffic handling (e.g., allow, deny).\n}"
  },
  {
    "path": "android/app/src/main/protos/v2/profile/profile.proto",
    "content": "syntax = \"proto3\";\n\npackage profile;\noption go_package = \"github.com/hiddify/hiddify-core/v2/profile\";\noption java_package = \"com.hiddify.core.api.v2.profile\";\nimport \"v2/hiddifyoptions/hiddify_options.proto\";\n\n// ProfileEntity defines a profile entity.\nmessage ProfileEntity {\n  string id = 1; // Unique identifier for the profile.\n  // bool active = 2; // Indicates if the profile is active.\n  string name = 3; // Name of the profile.\n  string url = 4; // URL associated with the profile.\n  int64 last_update = 5; // Last update time in milliseconds of the profile.\n  ProfileOptions options = 6; // Options associated with the profile.\n  SubscriptionInfo sub_info = 7; // Subscription-related information.\n  hiddifyoptions.HiddifyOptions override_hiddify_options = 8; // Override Hiddify options.\n}\n\n// ProfileOptions defines options for a profile.\nmessage ProfileOptions {\n  int64 update_interval = 1; // Update interval in milliseconds.\n}\n\n// SubscriptionInfo defines subscription-related information.\nmessage SubscriptionInfo {\n  int64 upload = 1; // Upload speed in bytes.\n  int64 download = 2; // Download speed in bytes.\n  int64 total = 3; // Total data in bytes.\n  int64 expire = 4; // Expiration time in milliseconds of the subscription.\n  string web_page_url = 5; // URL for the web page.\n  string support_url = 6; // URL for support.\n}"
  },
  {
    "path": "android/app/src/main/protos/v2/profile/profile_service.proto",
    "content": "syntax = \"proto3\";\n\npackage profile;\noption go_package = \"github.com/hiddify/hiddify-core/v2/profile\";\noption java_package = \"com.hiddify.core.api.v2.profile\";\n/**\n * This proto file defines the ProfileService with RPC methods \n * to manage profiles (add, fetch, update, delete, and set active profiles).\n */\n\n// Import dependencies\nimport \"v2/profile/profile.proto\"; // Import the ProfileEntity message from another proto file.\nimport \"v2/hcommon/common.proto\";   // Import the common response codes and messages.\n\n/**\n * ProfileRequest is the request message for fetching or identifying\n * a profile by ID, name, or URL.\n */\nmessage ProfileRequest {\n  string id = 1;    // The ID of the profile to fetch (Fastest and recommended).\n  string name = 2;  // The name of the profile to fetch (if both 'id' and 'url' are empty).\n  string url = 3;   // The URL of the profile to fetch (if both 'id' and 'name' are empty).  \n}\n\n/**\n * AddProfileRequest is the request message for adding a profile\n * via URL or content.\n */\nmessage AddProfileRequest {\n  string url = 1;        // The URL of the profile to add.\n  string content = 2;    // The profile content to add (used if 'url' is empty).\n  string name = 3;       // The optional name of the profile.\n  bool mark_as_active = 4; // Whether to mark the profile as active.\n}\n\n/**\n * ProfileResponse is the response message for profile service operations.\n */\nmessage ProfileResponse {\n  ProfileEntity profile = 1;  // The profile entity, populated in successful operations.\n  hcommon.ResponseCode response_code = 2;   // The response code indicating success or failure.\n  string message = 3;   // A message indicating the result or error, if any.\n}\n\n/**\n * MultiProfilesResponse is the response message for fetching multi profiles.\n */\nmessage MultiProfilesResponse {\n  repeated ProfileEntity profiles = 1;  // A list of profile entities.\n  hcommon.ResponseCode response_code = 2;   // The response code indicating success or failure.\n  string message = 3;   // A message indicating the result or error, if any.\n}\n\n/**\n * ProfileService defines the RPC methods available for managing profiles.\n */\nservice ProfileService {\n\n  /**\n   * GetProfile fetches a profile by ID, name, or URL.\n   */\n  rpc GetProfile(ProfileRequest) returns (ProfileResponse);\n\n  /**\n   * UpdateProfile updates an existing profile.\n   */\n  rpc UpdateProfile(ProfileEntity) returns (ProfileResponse);\n\n  /**\n   * GetAllProfiles fetches all profiles.\n   */\n  rpc GetAllProfiles(hcommon.Empty) returns (MultiProfilesResponse);\n\n  /**\n   * GetActiveProfile retrieves the currently active profile.\n   */\n  rpc GetActiveProfile(hcommon.Empty) returns (ProfileResponse);\n\n  /**\n   * SetActiveProfile sets a profile as active, identified by ID, name, or URL.\n   */\n  rpc SetActiveProfile(ProfileRequest) returns (hcommon.Response);\n\n  /**\n   * AddProfile adds a new profile using either a URL or the raw profile content.\n   */\n  rpc AddProfile(AddProfileRequest) returns (ProfileResponse);\n\n  /**\n   * DeleteProfile deletes a profile identified by ID, name, or URL.\n   */\n  rpc DeleteProfile(ProfileRequest) returns (hcommon.Response);\n}"
  },
  {
    "path": "android/app/src/main/res/drawable/android12splash.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"2048\"\n    android:viewportHeight=\"2048\">\n  <group android:scaleX=\"0.85\"\n      android:scaleY=\"0.85\"\n      android:translateX=\"153.6\"\n      android:translateY=\"153.6\">\n    <group>\n      <clip-path\n          android:pathData=\"M645,608h795v795h-795z\"/>\n      <path\n          android:pathData=\"M1230.8,787.2C1230.8,779.9 1234.6,773.1 1240.9,769.3L1408.3,668.9C1422.3,660.5 1440,670.5 1440,686.8V859C1440,870.6 1430.6,880 1419.1,880H1251.7C1240.2,880 1230.8,870.6 1230.8,859V787.2Z\"\n          android:fillColor=\"#455FE9\"/>\n      <path\n          android:pathData=\"M937.9,954.6C937.9,947.3 941.8,940.4 948.1,936.7L1115.4,836.2C1129.4,827.9 1147.1,837.9 1147.1,854.2V1152V1172.9V1361.2C1147.1,1372.7 1137.7,1382.1 1126.2,1382.1H958.8C947.3,1382.1 937.9,1372.7 937.9,1361.2V1172.9V1152V954.6ZM655.2,1124.9C648.9,1128.7 645,1135.6 645,1142.9V1361.2C645,1372.7 654.4,1382.1 665.9,1382.1H833.3C844.8,1382.1 854.2,1372.7 854.2,1361.2V1042.5C854.2,1026.2 836.5,1016.2 822.5,1024.5L655.2,1124.9Z\"\n          android:fillColor=\"#455FE9\"\n          android:fillType=\"evenOdd\"/>\n      <path\n          android:pathData=\"M854.2,1172.9H728.7V1340.3H854.2V1298.4C854.2,1286.9 863.6,1277.5 875.1,1277.5H917C928.5,1277.5 937.9,1286.9 937.9,1298.4V1340.3H1105.3V1172.9H937.9V1214.7C937.9,1226.3 928.5,1235.6 917,1235.6H875.1C863.6,1235.6 854.2,1226.3 854.2,1214.7V1172.9Z\"\n          android:fillColor=\"#455FE9\"\n          android:fillType=\"evenOdd\"/>\n      <path\n          android:pathData=\"M1230.8,942.8V1361.2C1230.8,1372.7 1240.2,1382.1 1251.7,1382.1H1419.1C1430.6,1382.1 1440,1372.7 1440,1361.2V942.8C1440,931.2 1430.6,921.8 1419.1,921.8H1251.7C1240.2,921.8 1230.8,931.2 1230.8,942.8Z\"\n          android:fillColor=\"#455FE9\"/>\n    </group>\n  </group>\n</vector>\n"
  },
  {
    "path": "android/app/src/main/res/drawable/ic_banner_foreground.xml",
    "content": "\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"640dp\"\n    android:height=\"360dp\"\n    android:viewportWidth=\"640\"\n    android:viewportHeight=\"360\">\n\n<group android:scaleX=\"0.6666667\"\n      android:scaleY=\"0.6666667\"\n      android:translateX=\"110\"\n      android:translateY=\"65\">\n      <group>\n        <clip-path\n            android:pathData=\"M60,115.28h114.5v113.28h-114.5z\"/>\n        <path\n            android:pathData=\"M144.37,140.82C144.37,139.77 144.92,138.8 145.83,138.26L169.93,123.95C171.94,122.76 174.49,124.19 174.49,126.51V151.05C174.49,152.7 173.15,154.03 171.48,154.03H147.38C145.71,154.03 144.37,152.7 144.37,151.05V140.82Z\"\n            android:fillColor=\"#455FE9\"/>\n        <path\n            android:pathData=\"M102.18,164.67C102.18,163.62 102.74,162.65 103.64,162.11L127.75,147.8C129.76,146.61 132.31,148.04 132.31,150.36V192.79V195.77V222.6C132.31,224.25 130.96,225.58 129.3,225.58H105.2C103.53,225.58 102.18,224.25 102.18,222.6V195.77V192.79V164.67ZM61.46,188.94C60.56,189.48 60,190.45 60,191.5V222.6C60,224.25 61.35,225.58 63.01,225.58H87.12C88.78,225.58 90.13,224.25 90.13,222.6V177.19C90.13,174.87 87.58,173.44 85.57,174.63L61.46,188.94Z\"\n            android:fillColor=\"#455FE9\"\n            android:fillType=\"evenOdd\"/>\n        <path\n            android:pathData=\"M90.13,195.77H72.05V219.62H90.13V213.66C90.13,212.01 91.48,210.68 93.14,210.68H99.17C100.83,210.68 102.18,212.01 102.18,213.66V219.62H126.29V195.77H102.18V201.73C102.18,203.38 100.83,204.71 99.17,204.71H93.14C91.48,204.71 90.13,203.38 90.13,201.73V195.77Z\"\n            android:fillColor=\"#455FE9\"\n            android:fillType=\"evenOdd\"/>\n        <path\n            android:pathData=\"M144.37,162.98V222.6C144.37,224.25 145.71,225.58 147.38,225.58H171.48C173.15,225.58 174.49,224.25 174.49,222.6V162.98C174.49,161.33 173.15,160 171.48,160H147.38C145.71,160 144.37,161.33 144.37,162.98Z\"\n            android:fillColor=\"#455FE9\"/>\n      </group>\n      <path\n          android:pathData=\"M536.46,237.06C531.61,237.06 528.04,235.92 525.75,233.66C523.5,231.43 522.38,227.88 522.38,223.01C522.38,221.42 523.18,220.63 524.78,220.63C526.38,220.63 527.18,221.42 527.18,223.01C527.18,226.56 527.85,228.99 529.19,230.32C530.56,231.64 532.98,232.3 536.46,232.3H555.46C558.97,232.3 561.4,231.64 562.73,230.32C564.07,228.99 564.74,226.56 564.74,223.01V207.04C562.64,209.68 559.89,211.59 556.49,212.76C553.14,213.93 549.13,214.51 544.47,214.51H542.07C535.2,214.51 530.2,212.97 527.07,209.87C523.94,206.77 522.38,201.86 522.38,195.14V164.44C522.38,162.86 523.18,162.07 524.78,162.07C526.38,162.07 527.18,162.86 527.18,164.44V195.14C527.18,200.58 528.27,204.38 530.45,206.53C532.66,208.68 536.53,209.76 542.07,209.76H544.47C551.3,209.76 556.38,208.55 559.7,206.13C563.06,203.68 564.74,200.01 564.74,195.14V164.44C564.74,162.86 565.54,162.07 567.14,162.07C568.75,162.07 569.55,162.86 569.55,164.44V223.01C569.55,227.88 568.42,231.43 566.17,233.66C563.92,235.92 560.35,237.06 555.46,237.06H536.46Z\"\n          android:fillColor=\"#495057\"/>\n      <path\n          android:pathData=\"M491.05,214.4C489.45,214.4 488.64,213.61 488.64,212.02V166.94H483.61C482,166.94 481.2,166.15 481.2,164.56C481.2,162.97 482,162.18 483.61,162.18H488.64V155.72C488.64,148.93 490.21,143.98 493.34,140.88C496.47,137.79 501.47,136.24 508.34,136.24C510.02,136.24 510.86,137.03 510.86,138.62C510.86,140.2 510.02,141 508.34,141C502.84,141 498.99,142.09 496.77,144.28C494.56,146.47 493.45,150.29 493.45,155.72V162.18H508.45C510.05,162.18 510.86,162.97 510.86,164.56C510.86,166.15 510.05,166.94 508.45,166.94H493.45V212.02C493.45,213.61 492.65,214.4 491.05,214.4Z\"\n          android:fillColor=\"#495057\"/>\n      <path\n          android:pathData=\"M463.89,151.53C461.6,151.53 460.46,150.36 460.46,148.02V145.7C460.46,143.43 461.6,142.3 463.89,142.3H466.24C468.49,142.3 469.62,143.43 469.62,145.7V148.02C469.62,150.36 468.49,151.53 466.24,151.53H463.89ZM465.1,214.4C463.49,214.4 462.69,213.61 462.69,212.02V164.56C462.69,162.97 463.49,162.18 465.1,162.18C466.7,162.18 467.5,162.97 467.5,164.56V212.02C467.5,213.61 466.7,214.4 465.1,214.4Z\"\n          android:fillColor=\"#495057\"/>\n      <path\n          android:pathData=\"M413.71,214.4C406.73,214.4 401.63,212.84 398.43,209.7C395.26,206.53 393.68,201.49 393.68,194.58V182C393.68,175.09 395.26,170.07 398.43,166.94C401.63,163.77 406.73,162.18 413.71,162.18H438.33V138.62C438.33,137.03 439.13,136.24 440.73,136.24C442.34,136.24 443.14,137.03 443.14,138.62V212.02C443.14,213.61 442.34,214.4 440.73,214.4C439.13,214.4 438.33,213.61 438.33,212.02V205.79C436.73,208.63 434.28,210.78 431,212.25C427.76,213.68 423.45,214.4 418.06,214.4H413.71ZM413.71,209.64H418.06C424.32,209.64 429.27,208.63 432.89,206.59C436.52,204.51 438.33,201.41 438.33,197.3V166.94H413.71C408.1,166.94 404.15,168.07 401.86,170.34C399.61,172.56 398.48,176.45 398.48,182V194.58C398.48,200.13 399.61,204.04 401.86,206.3C404.15,208.53 408.1,209.64 413.71,209.64Z\"\n          android:fillColor=\"#495057\"/>\n      <path\n          android:pathData=\"M345.84,214.4C338.86,214.4 333.76,212.84 330.56,209.7C327.39,206.53 325.81,201.49 325.81,194.58V182C325.81,175.09 327.39,170.07 330.56,166.94C333.76,163.77 338.86,162.18 345.84,162.18H370.46V138.62C370.46,137.03 371.26,136.24 372.86,136.24C374.47,136.24 375.27,137.03 375.27,138.62V212.02C375.27,213.61 374.47,214.4 372.86,214.4C371.26,214.4 370.46,213.61 370.46,212.02V205.79C368.86,208.63 366.41,210.78 363.13,212.25C359.89,213.68 355.58,214.4 350.19,214.4H345.84ZM345.84,209.64H350.19C356.45,209.64 361.39,208.63 365.02,206.59C368.65,204.51 370.46,201.41 370.46,197.3V166.94H345.84C340.23,166.94 336.28,168.07 333.99,170.34C331.74,172.56 330.61,176.45 330.61,182V194.58C330.61,200.13 331.74,204.04 333.99,206.3C336.28,208.53 340.23,209.64 345.84,209.64Z\"\n          android:fillColor=\"#495057\"/>\n      <path\n          android:pathData=\"M302.77,151.53C300.48,151.53 299.34,150.36 299.34,148.02V145.7C299.34,143.43 300.48,142.3 302.77,142.3H305.12C307.37,142.3 308.5,143.43 308.5,145.7V148.02C308.5,150.36 307.37,151.53 305.12,151.53H302.77ZM303.97,214.4C302.37,214.4 301.57,213.61 301.57,212.02V164.56C301.57,162.97 302.37,162.18 303.97,162.18C305.58,162.18 306.38,162.97 306.38,164.56V212.02C306.38,213.61 305.58,214.4 303.97,214.4Z\"\n          android:fillColor=\"#495057\"/>\n      <path\n          android:pathData=\"M225.37,214.4C224.57,214.4 223.96,214.21 223.54,213.84C223.16,213.42 222.97,212.82 222.97,212.02V145.07C222.97,144.28 223.16,143.7 223.54,143.32C223.96,142.9 224.57,142.7 225.37,142.7C226.17,142.7 226.76,142.9 227.15,143.32C227.57,143.7 227.77,144.28 227.77,145.07V175.66H276.21V145.07C276.21,144.28 276.4,143.7 276.78,143.32C277.2,142.9 277.81,142.7 278.61,142.7C279.41,142.7 280,142.9 280.39,143.32C280.8,143.7 281.02,144.28 281.02,145.07V212.02C281.02,212.82 280.8,213.42 280.39,213.84C280,214.21 279.41,214.4 278.61,214.4C277.81,214.4 277.2,214.21 276.78,213.84C276.4,213.42 276.21,212.82 276.21,212.02V180.42H227.77V212.02C227.77,212.82 227.57,213.42 227.15,213.84C226.76,214.21 226.17,214.4 225.37,214.4Z\"\n          android:fillColor=\"#495057\"/>\n\n  </group>\n</vector>"
  },
  {
    "path": "android/app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"2048dp\"\n    android:height=\"2048dp\"\n    android:viewportWidth=\"2048\"\n    android:viewportHeight=\"2048\">\n  <group>\n    <!-- Filled rectangle -->\n    <path\n        android:pathData=\"M0,0 L2048,0 L2048,2048 L0,2048 Z\"\n        android:fillColor=\"#FFF0F3FA\" />\n  </group>\n</vector>\n"
  },
  {
    "path": "android/app/src/main/res/drawable/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"2048\"\n    android:viewportHeight=\"2048\">\n  <group android:scaleX=\"0.85\"\n      android:scaleY=\"0.85\"\n      android:translateX=\"153.6\"\n      android:translateY=\"153.6\">\n    <group>\n      <clip-path\n          android:pathData=\"M645,608h795v795h-795z\"/>\n      <path\n          android:pathData=\"M1230.8,787.2C1230.8,779.9 1234.6,773.1 1240.9,769.3L1408.3,668.9C1422.3,660.5 1440,670.5 1440,686.8V859C1440,870.6 1430.6,880 1419.1,880H1251.7C1240.2,880 1230.8,870.6 1230.8,859V787.2Z\"\n          android:fillColor=\"#455FE9\"/>\n      <path\n          android:pathData=\"M937.9,954.6C937.9,947.3 941.8,940.4 948.1,936.7L1115.4,836.2C1129.4,827.9 1147.1,837.9 1147.1,854.2V1152V1172.9V1361.2C1147.1,1372.7 1137.7,1382.1 1126.2,1382.1H958.8C947.3,1382.1 937.9,1372.7 937.9,1361.2V1172.9V1152V954.6ZM655.2,1124.9C648.9,1128.7 645,1135.6 645,1142.9V1361.2C645,1372.7 654.4,1382.1 665.9,1382.1H833.3C844.8,1382.1 854.2,1372.7 854.2,1361.2V1042.5C854.2,1026.2 836.5,1016.2 822.5,1024.5L655.2,1124.9Z\"\n          android:fillColor=\"#455FE9\"\n          android:fillType=\"evenOdd\"/>\n      <path\n          android:pathData=\"M854.2,1172.9H728.7V1340.3H854.2V1298.4C854.2,1286.9 863.6,1277.5 875.1,1277.5H917C928.5,1277.5 937.9,1286.9 937.9,1298.4V1340.3H1105.3V1172.9H937.9V1214.7C937.9,1226.3 928.5,1235.6 917,1235.6H875.1C863.6,1235.6 854.2,1226.3 854.2,1214.7V1172.9Z\"\n          android:fillColor=\"#455FE9\"\n          android:fillType=\"evenOdd\"/>\n      <path\n          android:pathData=\"M1230.8,942.8V1361.2C1230.8,1372.7 1240.2,1382.1 1251.7,1382.1H1419.1C1430.6,1382.1 1440,1372.7 1440,1361.2V942.8C1440,931.2 1430.6,921.8 1419.1,921.8H1251.7C1240.2,921.8 1230.8,931.2 1230.8,942.8Z\"\n          android:fillColor=\"#455FE9\"/>\n    </group>\n  </group>\n</vector>\n"
  },
  {
    "path": "android/app/src/main/res/drawable/launch_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item>\n        <bitmap android:gravity=\"fill\" android:src=\"@drawable/background\"/>\n    </item>\n    <item>\n        <bitmap android:gravity=\"center\" android:src=\"@drawable/splash\"/>\n    </item>\n</layer-list>\n"
  },
  {
    "path": "android/app/src/main/res/drawable-v21/launch_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item>\n        <bitmap android:gravity=\"fill\" android:src=\"@drawable/background\"/>\n    </item>\n    <item>\n        <bitmap android:gravity=\"center\" android:src=\"@drawable/splash\"/>\n    </item>\n</layer-list>\n"
  },
  {
    "path": "android/app/src/main/res/mipmap-anydpi-v26/ic_banner.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_banner_background\"/>\n    <foreground android:drawable=\"@drawable/ic_banner_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "android/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n</resources>"
  },
  {
    "path": "android/app/src/main/res/values/ic_banner_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"ic_banner_background\">#F0F3FA</color>\n</resources>"
  },
  {
    "path": "android/app/src/main/res/values/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"ic_launcher_background\">#F0F3FA</color>\n</resources>"
  },
  {
    "path": "android/app/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"stop\">Stop</string>\n    <string name=\"quick_toggle\">Toggle</string>\n    <string name=\"status_starting\">Service starting…</string>\n    <string name=\"status_started\">Service started</string>\n</resources>"
  },
  {
    "path": "android/app/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->\n    <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Light.NoTitleBar\">\n        <!-- Show a splash screen on the activity. Automatically removed when\n             the Flutter engine draws its first frame -->\n        <item name=\"android:windowBackground\">@drawable/launch_background</item>\n        <item name=\"android:forceDarkAllowed\">false</item>\n        <item name=\"android:windowFullscreen\">false</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">false</item>\n        <item name=\"android:windowLayoutInDisplayCutoutMode\">shortEdges</item>\n    </style>\n    <!-- Theme applied to the Android Window as soon as the process has started.\n         This theme determines the color of the Android Window while your\n         Flutter UI initializes, as well as behind your Flutter UI while its\n         running.\n\n         This Theme is only used starting with V2 of Flutter's Android embedding. -->\n    <style name=\"NormalTheme\" parent=\"@android:style/Theme.Light.NoTitleBar\">\n        <item name=\"android:windowBackground\">?android:colorBackground</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "android/app/src/main/res/values-night/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->\n    <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Black.NoTitleBar\">\n        <!-- Show a splash screen on the activity. Automatically removed when\n             the Flutter engine draws its first frame -->\n        <item name=\"android:windowBackground\">@drawable/launch_background</item>\n        <item name=\"android:forceDarkAllowed\">false</item>\n        <item name=\"android:windowFullscreen\">false</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">false</item>\n        <item name=\"android:windowLayoutInDisplayCutoutMode\">shortEdges</item>\n    </style>\n    <!-- Theme applied to the Android Window as soon as the process has started.\n         This theme determines the color of the Android Window while your\n         Flutter UI initializes, as well as behind your Flutter UI while its\n         running.\n\n         This Theme is only used starting with V2 of Flutter's Android embedding. -->\n    <style name=\"NormalTheme\" parent=\"@android:style/Theme.Black.NoTitleBar\">\n        <item name=\"android:windowBackground\">?android:colorBackground</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "android/app/src/main/res/values-night-v31/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->\n    <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Black.NoTitleBar\">\n        <item name=\"android:forceDarkAllowed\">false</item>\n        <item name=\"android:windowFullscreen\">false</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">false</item>\n        <item name=\"android:windowLayoutInDisplayCutoutMode\">shortEdges</item>\n        <item name=\"android:windowSplashScreenBackground\">#F0F3FA</item>\n        <item name=\"android:windowSplashScreenAnimatedIcon\">@drawable/android12splash</item>\n    </style>\n    <!-- Theme applied to the Android Window as soon as the process has started.\n         This theme determines the color of the Android Window while your\n         Flutter UI initializes, as well as behind your Flutter UI while its\n         running.\n         \n         This Theme is only used starting with V2 of Flutter's Android embedding. -->\n    <style name=\"NormalTheme\" parent=\"@android:style/Theme.Black.NoTitleBar\">\n        <item name=\"android:windowBackground\">?android:colorBackground</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "android/app/src/main/res/values-v31/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->\n    <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Light.NoTitleBar\">\n        <item name=\"android:forceDarkAllowed\">false</item>\n        <item name=\"android:windowFullscreen\">false</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">false</item>\n        <item name=\"android:windowLayoutInDisplayCutoutMode\">shortEdges</item>\n        <item name=\"android:windowSplashScreenBackground\">#ffffff</item>\n        <item name=\"android:windowSplashScreenAnimatedIcon\">@drawable/android12splash</item>\n    </style>\n    <!-- Theme applied to the Android Window as soon as the process has started.\n         This theme determines the color of the Android Window while your\n         Flutter UI initializes, as well as behind your Flutter UI while its\n         running.\n         \n         This Theme is only used starting with V2 of Flutter's Android embedding. -->\n    <style name=\"NormalTheme\" parent=\"@android:style/Theme.Light.NoTitleBar\">\n        <item name=\"android:windowBackground\">?android:colorBackground</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "android/app/src/main/res/xml/network_security_config.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<network-security-config>\n    <domain-config cleartextTrafficPermitted=\"true\">\n        <domain includeSubdomains=\"false\">127.0.0.1</domain>\n    </domain-config>\n</network-security-config>"
  },
  {
    "path": "android/app/src/main/res/xml/shortcuts.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shortcuts xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <shortcut\n        android:icon=\"@mipmap/ic_launcher\"\n        android:shortcutId=\"toggle\"\n        android:shortcutLongLabel=\"@string/quick_toggle\"\n        android:shortcutShortLabel=\"@string/quick_toggle\">\n        <intent\n            android:action=\"android.intent.action.MAIN\"\n            android:targetClass=\"com.hiddify.hiddify.ShortcutActivity\"\n            android:targetPackage=\"app.hiddify.com\" />\n    </shortcut>\n</shortcuts>"
  },
  {
    "path": "android/app/src/profile/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <!-- The INTERNET permission is required for development. Specifically,\n         the Flutter tool needs it to communicate with the running application\n         to allow setting breakpoints, to provide hot reload, etc.\n    -->\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n</manifest>\n"
  },
  {
    "path": "android/build.gradle",
    "content": "allprojects {\n    repositories {\n        mavenCentral()\n        google()\n    }\n\n}\n\n\nrootProject.buildDir = '../build'\nsubprojects {\n    project.buildDir = \"${rootProject.buildDir}/${project.name}\"\n}\nsubprojects {\n    project.evaluationDependsOn(':app')\n}\n\ntasks.register(\"clean\", Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "android/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.7-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "android/gradle.properties",
    "content": "org.gradle.jvmargs=-Xmx4048m -Dfile.encoding=UTF-8\nandroid.useAndroidX=true\nandroid.enableJetifier=true\nandroid.defaults.buildfeatures.buildconfig=true\nandroid.nonTransitiveRClass=false\nandroid.nonFinalResIds=false\n\n\norg.gradle.daemon=true\norg.gradle.parallel=true\norg.gradle.configureondemand=true\norg.gradle.caching=true"
  },
  {
    "path": "android/settings.gradle",
    "content": "pluginManagement {\n    def flutterSdkPath = {\n        def properties = new Properties()\n        file(\"local.properties\").withInputStream { properties.load(it) }\n        def flutterSdkPath = properties.getProperty(\"flutter.sdk\")\n        assert flutterSdkPath != null, \"flutter.sdk not set in local.properties\"\n        return flutterSdkPath\n    }()\n\n    includeBuild(\"$flutterSdkPath/packages/flutter_tools/gradle\")\n\n    repositories {\n        mavenCentral()\n        google()\n        gradlePluginPortal()\n    }\n}\n\n\nplugins {\n    id \"dev.flutter.flutter-plugin-loader\" version \"1.0.0\"\n    id \"com.android.application\" version '8.6.0' apply false\n    id \"org.jetbrains.kotlin.android\" version \"2.1.0\" apply false\n}\n\ninclude \":app\""
  },
  {
    "path": "appcast.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<rss version=\"2.0\" xmlns:sparkle=\"http://www.andymatuschak.org/xml-namespaces/sparkle\">\n    <channel>\n        <title>Release</title>\n        <item>\n            <title>Version 0.13.6</title>\n            <pubDate>Sun, 7 Jan 2024 22:00:00 +0000</pubDate>\n            <enclosure\n                url=\"https://play.google.com/store/apps/details?id=app.hiddify.com\"\n                sparkle:version=\"0.13.6\" sparkle:os=\"android\" />\n        </item>\n        <item>\n            <title>Version 0.13.6</title>\n            <pubDate>Sun, 7 Jan 2024 22:00:00 +0000</pubDate>\n            <enclosure\n                url=\"hhttps://apps.apple.com/us/app/hiddify-proxy-vpn/id6596777532\"\n                sparkle:version=\"0.13.6\" sparkle:os=\"ios\" />\n        </item>\n        <item>\n            <title>Version 0.13.6</title>\n            <pubDate>Sun, 7 Jan 2024 22:00:00 +0000</pubDate>\n            <enclosure\n                url=\"https://github.com/hiddify/hiddify-app/releases/download/v0.13.6/hiddify-windows-x64-setup.zip\"\n                sparkle:version=\"0.13.6\" sparkle:os=\"windows\" />\n        </item>\n        <item>\n            <title>Version 0.13.6</title>\n            <pubDate>Sun, 7 Jan 2024 22:00:00 +0000</pubDate>\n            <enclosure\n                url=\"https://github.com/hiddify/hiddify-app/releases/download/v0.13.6/hiddify-macos-universal.zip\"\n                sparkle:version=\"0.13.6\" sparkle:os=\"macos\" />\n        </item>\n        <item>\n            <title>Version 0.13.6</title>\n            <pubDate>Sun, 7 Jan 2024 22:00:00 +0000</pubDate>\n            <enclosure\n                url=\"https://github.com/hiddify/hiddify-app/releases/download/v0.13.6/hiddify-linux-x64.zip\"\n                sparkle:version=\"0.13.6\" sparkle:os=\"linux\" />\n        </item>\n    </channel>\n</rss>"
  },
  {
    "path": "assets/core/.gitkeep",
    "content": ""
  },
  {
    "path": "assets/fonts/emoji_source.txt",
    "content": "https://github.com/hiddify-com/noto-emoji\n\n\npyftsubset \"Emoji3.ttf\" --output-file=Emoji.ttf --unicodes=U+1F1E6+1F1E9,U+1F1E6+1F1EA,U+1F1E6+1F1EB,U+1F1E6+1F1EC,U+1F1E6+1F1EE,U+1F1E6+1F1F1,U+1F1E6+1F1F2,U+1F1E6+1F1F4,U+1F1E6+1F1F6,U+1F1E6+1F1F7,U+1F1E6+1F1F8,U+1F1E6+1F1F9,U+1F1E6+1F1FA,U+1F1E6+1F1FC,U+1F1E6+1F1FD,U+1F1E6+1F1FF,U+1F1E7+1F1E6,U+1F1E7+1F1E7,U+1F1E7+1F1E9,U+1F1E7+1F1EA,U+1F1E7+1F1EB,U+1F1E7+1F1EC,U+1F1E7+1F1ED,U+1F1E7+1F1EE,U+1F1E7+1F1EF,U+1F1E7+1F1F1,U+1F1E7+1F1F2,U+1F1E7+1F1F3,U+1F1E7+1F1F4,U+1F1E7+1F1F6,U+1F1E7+1F1F7,U+1F1E7+1F1F8,U+1F1E7+1F1F9,U+1F1E7+1F1FB,U+1F1E7+1F1FC,U+1F1E7+1F1FE,U+1F1E7+1F1FF,U+1F1E8+1F1E6,U+1F1E8+1F1E8,U+1F1E8+1F1E9,U+1F1E8+1F1EB,U+1F1E8+1F1EC,U+1F1E8+1F1ED,U+1F1E8+1F1EE,U+1F1E8+1F1F0,U+1F1E8+1F1F1,U+1F1E8+1F1F2,U+1F1E8+1F1F3,U+1F1E8+1F1F4,U+1F1E8+1F1F7,U+1F1E8+1F1FA,U+1F1E8+1F1FB,U+1F1E8+1F1FC,U+1F1E8+1F1FD,U+1F1E8+1F1FE,U+1F1E8+1F1FF,U+1F1E9+1F1EA,U+1F1E9+1F1EF,U+1F1E9+1F1F0,U+1F1E9+1F1F2,U+1F1E9+1F1F4,U+1F1E9+1F1FF,U+1F1EA+1F1E8,U+1F1EA+1F1EA,U+1F1EA+1F1EC,U+1F1EA+1F1ED,U+1F1EA+1F1F7,U+1F1EA+1F1F8,U+1F1EA+1F1F9,U+1F1EB+1F1EE,U+1F1EB+1F1EF,U+1F1EB+1F1F0,U+1F1EB+1F1F2,U+1F1EB+1F1F4,U+1F1EB+1F1F7,U+1F1EC+1F1E6,U+1F1EC+1F1E7,U+1F1EC+1F1E9,U+1F1EC+1F1EA,U+1F1EC+1F1EB,U+1F1EC+1F1EC,U+1F1EC+1F1ED,U+1F1EC+1F1EE,U+1F1EC+1F1F1,U+1F1EC+1F1F2,U+1F1EC+1F1F3,U+1F1EC+1F1F5,U+1F1EC+1F1F6,U+1F1EC+1F1F7,U+1F1EC+1F1F8,U+1F1EC+1F1F9,U+1F1EC+1F1FA,U+1F1EC+1F1FC,U+1F1EC+1F1FE,U+1F1ED+1F1F0,U+1F1ED+1F1F2,U+1F1ED+1F1F3,U+1F1ED+1F1F7,U+1F1ED+1F1F9,U+1F1ED+1F1FA,U+1F1EE+1F1E9,U+1F1EE+1F1EA,U+1F1EE+1F1F1,U+1F1EE+1F1F2,U+1F1EE+1F1F3,U+1F1EE+1F1F4,U+1F1EE+1F1F6,U+1F1EE+1F1F7,U+1F1EE+1F1F8,U+1F1EE+1F1F9,U+1F1EF+1F1EA,U+1F1EF+1F1F2,U+1F1EF+1F1F4,U+1F1EF+1F1F5,U+1F1F0+1F1EA,U+1F1F0+1F1EC,U+1F1F0+1F1ED,U+1F1F0+1F1EE,U+1F1F0+1F1F2,U+1F1F0+1F1F3,U+1F1F0+1F1F5,U+1F1F0+1F1F7,U+1F1F0+1F1FC,U+1F1F0+1F1FE,U+1F1F0+1F1FF,U+1F1F1+1F1E6,U+1F1F1+1F1E7,U+1F1F1+1F1E8,U+1F1F1+1F1EE,U+1F1F1+1F1F0,U+1F1F1+1F1F7,U+1F1F1+1F1F8,U+1F1F1+1F1F9,U+1F1F1+1F1FA,U+1F1F1+1F1FB,U+1F1F1+1F1FE,U+1F1F2+1F1E6,U+1F1F2+1F1E8,U+1F1F2+1F1E9,U+1F1F2+1F1EA,U+1F1F2+1F1EB,U+1F1F2+1F1EC,U+1F1F2+1F1ED,U+1F1F2+1F1F0,U+1F1F2+1F1F1,U+1F1F2+1F1F2,U+1F1F2+1F1F3,U+1F1F2+1F1F4,U+1F1F2+1F1F5,U+1F1F2+1F1F6,U+1F1F2+1F1F7,U+1F1F2+1F1F8,U+1F1F2+1F1F9,U+1F1F2+1F1FA,U+1F1F2+1F1FB,U+1F1F2+1F1FC,U+1F1F2+1F1FD,U+1F1F2+1F1FE,U+1F1F2+1F1FF,U+1F1F3+1F1E6,U+1F1F3+1F1E8,U+1F1F3+1F1EA,U+1F1F3+1F1EB,U+1F1F3+1F1EC,U+1F1F3+1F1EE,U+1F1F3+1F1F1,U+1F1F3+1F1F4,U+1F1F3+1F1F5,U+1F1F3+1F1F7,U+1F1F3+1F1FA,U+1F1F3+1F1FF,U+1F1F4+1F1F2,U+1F1F5+1F1E6,U+1F1F5+1F1EA,U+1F1F5+1F1EB,U+1F1F5+1F1EC,U+1F1F5+1F1ED,U+1F1F5+1F1F0,U+1F1F5+1F1F1,U+1F1F5+1F1F2,U+1F1F5+1F1F3,U+1F1F5+1F1F7,U+1F1F5+1F1F8,U+1F1F5+1F1F9,U+1F1F5+1F1FC,U+1F1F5+1F1FE,U+1F1F6+1F1E6,U+1F1F7+1F1EA,U+1F1F7+1F1F4,U+1F1F7+1F1F8,U+1F1F7+1F1FA,U+1F1F7+1F1FC,U+1F1F8+1F1E6,U+1F1F8+1F1E7,U+1F1F8+1F1E8,U+1F1F8+1F1E9,U+1F1F8+1F1EA,U+1F1F8+1F1EC,U+1F1F8+1F1ED,U+1F1F8+1F1EE,U+1F1F8+1F1EF,U+1F1F8+1F1F0,U+1F1F8+1F1F1,U+1F1F8+1F1F2,U+1F1F8+1F1F3,U+1F1F8+1F1F4,U+1F1F8+1F1F7,U+1F1F8+1F1F8,U+1F1F8+1F1F9,U+1F1F8+1F1FB,U+1F1F8+1F1FD,U+1F1F8+1F1FE,U+1F1F8+1F1FF,U+1F1F9+1F1E8,U+1F1F9+1F1E9,U+1F1F9+1F1EB,U+1F1F9+1F1EC,U+1F1F9+1F1ED,U+1F1F9+1F1EF,U+1F1F9+1F1F0,U+1F1F9+1F1F1,U+1F1F9+1F1F2,U+1F1F9+1F1F3,U+1F1F9+1F1F4,U+1F1F9+1F1F7,U+1F1F9+1F1F9,U+1F1F9+1F1FB,U+1F1F9+1F1FC,U+1F1F9+1F1FF,U+1F1FA+1F1E6,U+1F1FA+1F1EC,U+1F1FA+1F1F2,U+1F1FA+1F1F8,U+1F1FA+1F1FE,U+1F1FA+1F1FF,U+1F1FB+1F1E6,U+1F1FB+1F1E8,U+1F1FB+1F1EA,U+1F1FB+1F1EC,U+1F1FB+1F1EE,U+1F1FB+1F1F3,U+1F1FB+1F1FA,U+1F1FC+1F1EB,U+1F1FC+1F1F8,U+1F1FE+1F1EA,U+1F1FE+1F1F9,U+1F1FF+1F1E6,U+1F1FF+1F1F2,U+1F1FF+1F1FC\n"
  },
  {
    "path": "assets/images/convert_icon.sh",
    "content": "in=$1\nconvert -define icon:auto-resize=128,64,48,32,16 -gravity center  $in.png   $in.ico\n"
  },
  {
    "path": "assets/translations/ar.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"Hiddify\",\n    \"start\": \"ابدأ\",\n    \"version\": \"الإصدار\",\n    \"ok\": \"موافق\",\n    \"cancel\": \"إلغاء\",\n    \"kContinue\": \"متابعة\",\n    \"showMore\": \"عرض المزيد\",\n    \"showLess\": \"عرض أقل\",\n    \"filter\": \"تصفية\",\n    \"all\": \"الكل\",\n    \"pause\": \"إيقاف مؤقت\",\n    \"resume\": \"استئناف\",\n    \"clear\": \"مسح\",\n    \"close\": \"إغلاق\",\n    \"auto\": \"تلقائي\",\n    \"manually\": \"يدوي\",\n    \"name\": \"الاسم\",\n    \"url\": \"الرابط\",\n    \"add\": \"إضافة\",\n    \"clipboard\": \"الحافظة\",\n    \"addToClipboard\": \"إضافة إلى الحافظة\",\n    \"scanQr\": \"مسح رمز QR\",\n    \"free\": \"مجاني\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Fragment\",\n    \"help\": \"مساعدة\",\n    \"save\": \"حفظ\",\n    \"update\": \"تحديث\",\n    \"share\": \"مشاركة\",\n    \"edit\": \"تعديل\",\n    \"delete\": \"حذف\",\n    \"discard\": \"تجاهل\",\n    \"import\": \"استيراد\",\n    \"export\": \"تصدير\",\n    \"later\": \"لاحقًا\",\n    \"ignore\": \"تجاهل\",\n    \"quit\": \"خروج\",\n    \"notSet\": \"غير محدد\",\n    \"hide\": \"إخفاء\",\n    \"exit\": \"خروج\",\n    \"reset\": \"إعادة تعيين\",\n    \"done\": \"تم\",\n    \"search\": \"بحث\",\n    \"decline\": \"رفض\",\n    \"agree\": \"أوافق\",\n    \"empty\": \"فارغ\",\n    \"unknown\": \"غير معروف\",\n    \"hidden\": \"مخفي\",\n    \"timeout\": \"انتهى الوقت\",\n    \"sort\": \"فرز\",\n    \"dashboard\": \"لوحة التحكم\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"يوم واحد\",\n        \"two\": \"يومان\",\n        \"few\": \"$n أيام\",\n        \"many\": \"$n يومًا\",\n        \"other\": \"$n يوم\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"ساعة واحدة\",\n        \"two\": \"ساعتان\",\n        \"few\": \"$n ساعات\",\n        \"many\": \"$n ساعة\",\n        \"other\": \"$n ساعة\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"تم رفض الإذن\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"تمت الإضافة إلى الحافظة بنجاح\",\n          \"failure\": \"فشل النسخ إلى الحافظة\",\n          \"contentTooLarge\": \"المحتوى كبير جدًا. استخدم تصدير الملف بدلاً من ذلك\"\n        },\n        \"file\": {\n          \"success\": \"تم إنشاء ملف JSON بنجاح\",\n          \"failure\": \"فشل إنشاء الملف\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"تأكيد الاستيراد\",\n        \"success\": \"تم الاستيراد بنجاح\",\n        \"failure\": \"فشل الاستيراد\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"كل ما تحتاجه لإنترنت بلا قيود\",\n    \"termsAndPolicyCaution(rich)\": \"بالاستمرار، أنت توافق على ${tap(@:pages.about.termsAndConditions)}\",\n    \"info(rich)\": \"صُنع بـ ❤️ بواسطة Hiddify - ${tap_source(مفتوح المصدر)} (${tap_license(الرخصة)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"الرئيسية\",\n      \"quickSettings\": \"الإعدادات السريعة\"\n    },\n    \"proxies\": {\n      \"title\": \"البروكسيات\",\n      \"sort\": \"فرز البروكسيات\",\n      \"testDelay\": \"اختبار التأخير\",\n      \"empty\": \"لا توجد بروكسيات متاحة\",\n      \"activeProxy\": \"البروكسي النشط\",\n      \"unknownIp\": \"IP غير معروف\",\n      \"sortOptions\": {\n        \"unsorted\": \"الافتراضي\",\n        \"name\": \"أبجديًا\",\n        \"delay\": \"حسب التأخير\"\n      },\n      \"ipInfo\": {\n        \"address\": \"عنوان IP\",\n        \"country\": \"الدولة\",\n        \"organization\": \"المُنظمة\"\n      },\n      \"delay\": {\n        \"result\": \"التأخير: ${delay} مللي ثانية\",\n        \"timeout\": \"انتهى وقت اختبار التأخير\",\n        \"testing\": \"التأخير: قيد الاختبار...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"الملفات الشخصية\",\n      \"add\": \"إضافة ملف شخصي\",\n      \"update\": \"تحديث الملف الشخصي\",\n      \"viewAllProfiles\": \"عرض جميع الملفات الشخصية\",\n      \"activeProfileName\": \"اسم الملف النشط: \\\"${name}\\\".\",\n      \"nonActiveProfileName\": \"تحديد \\\"${name}\\\" كملف نشط\",\n      \"freeSubNotFound\": \"لم يتم العثور على اشتراك مجاني\",\n      \"freeSubNotFoundForRegion\": \"لم يتم العثور على اشتراك مجاني لمنطقة \\\"${region}\\\"\",\n      \"failedToLoad\": \"فشل التحميل\",\n      \"updateSubscriptions\": \"تحديث الاشتراكات\",\n      \"share\": {\n        \"urlToClipboard\": \"رابط URL إلى الحافظة\",\n        \"showUrlQr\": \"عرض رمز QR للرابط\",\n        \"jsonToClipboard\": \"JSON إلى الحافظة\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"تم حفظ الملف الشخصي بنجاح\"\n        },\n        \"invalidUrl\": \"رابط غير صالح\",\n        \"add\": {\n          \"failure\": \"فشل إضافة الملف الشخصي\"\n        },\n        \"update\": {\n          \"success\": \"تم تحديث الملف الشخصي بنجاح\",\n          \"successNamed\": \"تم تحديث \\\"${name}\\\" بنجاح\",\n          \"failure\": \"فشل تحديث الملف الشخصي\",\n          \"failureNamed\": \"فشل تحديث \\\"${name}\\\"\"\n        },\n        \"delete\": {\n          \"success\": \"تم حذف الملف الشخصي بنجاح\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"الملف الشخصي\",\n      \"lastUpdate\": \"آخر تحديث\",\n      \"form\": {\n        \"nameHint\": \"اسم الملف الشخصي\",\n        \"emptyName\": \"الاسم مطلوب\",\n        \"invalidUrl\": \"رابط غير صالح\",\n        \"urlHint\": \"رابط الإعدادات الكامل\",\n        \"disableAutoUpdate\": \"تعطيل التحديث التلقائي\",\n        \"autoUpdateInterval\": \"فاصل التحديث التلقائي\",\n        \"loading\": \"جاري إضافة الملف الشخصي...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"السجلات\",\n      \"shareCoreLogs\": \"مشاركة سجلات النواة\",\n      \"shareAppLogs\": \"مشاركة سجلات التطبيق\"\n    },\n    \"about\": {\n      \"title\": \"حول التطبيق\",\n      \"notAvailableMsg\": \"أنت تستخدم أحدث إصدار بالفعل\",\n      \"checkForUpdate\": \"التحقق من وجود تحديثات\",\n      \"openWorkingDir\": \"فتح مجلد العمل\",\n      \"sourceCode\": \"الكود المصدري\",\n      \"telegramChannel\": \"قناة التيليجرام\",\n      \"termsAndConditions\": \"الشروط والأحكام\",\n      \"privacyPolicy\": \"سياسة الخصوصية\"\n    },\n    \"settings\": {\n      \"title\": \"الإعدادات\",\n      \"resetTunnel\": \"إعادة تعيين ملف VPN\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"استيراد الخيارات من الحافظة\",\n          \"file\": \"استيراد الخيارات من ملف\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"نسخ الخيارات المجهولة إلى الحافظة\",\n          \"anonymousToFile\": \"تصدير الخيارات المجهولة إلى ملف\",\n          \"allToClipboard\": \"نسخ جميع الخيارات إلى الحافظة\",\n          \"allToFile\": \"تصدير جميع الخيارات إلى ملف\"\n        },\n        \"reset\": \"إعادة تعيين الخيارات\"\n      },\n      \"general\": {\n        \"title\": \"عام\",\n        \"locale\": \"اللغة\",\n        \"themeMode\": \"السمة\",\n        \"themeModes\": {\n          \"system\": \"سمة النظام الافتراضية\",\n          \"dark\": \"الوضع الداكن\",\n          \"light\": \"الوضع الفاتح\",\n          \"black\": \"الوضع الأسود\"\n        },\n        \"enableAnalytics\": \"تفعيل التحليلات\",\n        \"enableAnalyticsMsg\": \"السماح بجمع بيانات التحليل وتقارير الأعطال لتحسين التطبيق\",\n        \"autoIpCheck\": \"التحقق التلقائي من IP الاتصال\",\n        \"dynamicNotification\": \"عرض السرعة في الإشعار\",\n        \"hapticFeedback\": \"ردود الفعل اللمسية\",\n        \"actionAtClosing\": \"الإجراء عند الإغلاق\",\n        \"autoStart\": \"البدء عند تسجيل الدخول\",\n        \"silentStart\": \"البدء في الخلفية\",\n        \"ignoreBatteryOptimizations\": \"تجاهل تحسينات البطارية\",\n        \"ignoreBatteryOptimizationsMsg\": \"إزالة القيود للحصول على أفضل أداء للـ VPN\",\n        \"memoryLimit\": \"حد الذاكرة\",\n        \"memoryLimitMsg\": \"قم بتفعيل هذا الخيار إذا كنت تواجه أخطاء نفاد الذاكرة أو تعطل التطبيق بشكل متكرر\",\n        \"debugMode\": \"وضع التصحيح\",\n        \"debugModeMsg\": \"أعد تشغيل التطبيق لتطبيق هذا التغيير\",\n        \"logLevel\": \"مستوى السجل\",\n        \"connectionTestUrl\": \"رابط اختبار الاتصال\",\n        \"urlTestInterval\": \"فاصل اختبار الرابط\",\n        \"clashApiPort\": \"منفذ Clash API\",\n        \"useXrayCoreWhenPossible\": \"استخدام xray-core عند الإمكان\",\n        \"useXrayCoreWhenPossibleMsg\": \"استخدم xray-core عند تحليل روابط الاشتراك. تحتاج إلى إعادة استيراد الرابط لتفعيل هذا الخيار\"\n      },\n      \"routing\": {\n        \"title\": \"التوجيه\",\n        \"perAppProxy\": {\n          \"title\": \"بروكسي لكل تطبيق\",\n          \"hideSysApps\": \"إخفاء تطبيقات النظام\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"استيراد التحديد من الحافظة\",\n              \"file\": \"استيراد التحديد من ملف\",\n              \"msg\": \"سيؤدي الاستيراد إلى استبدال تحديداتك الحالية. هل أنت متأكد من رغبتك في المتابعة؟\"\n            },\n            \"export\": {\n              \"clipboard\": \"نسخ التحديد إلى الحافظة\",\n              \"file\": \"تصدير التحديد إلى ملف\"\n            },\n            \"shareToAll\": \"مشاركة مع الجميع\",\n            \"clearAllSelections\": \"مسح جميع التحديدات\"\n          },\n          \"modes\": {\n            \"all\": \"الكل\",\n            \"proxy\": \"بروكسي\",\n            \"bypass\": \"تجاوز\",\n            \"allMsg\": \"استخدام البروكسي لجميع التطبيقات\",\n            \"proxyMsg\": \"استخدام البروكسي للتطبيقات المحددة فقط\",\n            \"bypassMsg\": \"عدم استخدام البروكسي للتطبيقات المحددة\"\n          },\n          \"autoSelection\": {\n            \"title\": \"الاختيار التلقائي\",\n            \"performNow\": \"تنفيذ الآن\",\n            \"resetToDefault\": \"إعادة التعيين إلى الافتراضي\",\n            \"autoUpdateInterval\": \"فاصل التحديث التلقائي\",\n            \"toast\": {\n              \"success\": \"اكتمل الاختيار التلقائي للتطبيقات بنجاح\",\n              \"failure\": \"فشل الاختيار التلقائي\",\n              \"regionNotFound\": \"لم يتم العثور على اختيار تلقائي لمنطقة \\\"${region}\\\"\",\n              \"alreadyInAuto\": \"اختياراتك موجودة بالفعل في القائمة التلقائية\"\n            },\n            \"dialog\": {\n              \"title\": \"الاختيار التلقائي للتطبيقات\",\n              \"msg\": \"تم تعطيل ميزة الاختيار التلقائي للبروكسي بسبب تغيير المنطقة إلى \\\"${region}\\\"\"\n            }\n          }\n        },\n        \"region\": \"المنطقة\",\n        \"regions\": {\n          \"ir\": \"إيران (ir)\",\n          \"cn\": \"الصين (cn)\",\n          \"ru\": \"روسيا (ru)\",\n          \"af\": \"أفغانستان (af)\",\n          \"id\": \"إندونيسيا (id)\",\n          \"tr\": \"تركيا (tr)\",\n          \"br\": \"البرازيل (br)\",\n          \"other\": \"أخرى\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"استراتيجية Balancer\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"حظر الإعلانات\",\n        \"bypassLan\": \"تجاوز الشبكة المحلية\",\n        \"resolveDestination\": \"تحديد وجهة الاتصال\",\n        \"ipv6Route\": \"توجيه IPv6\",\n        \"ipv6Modes\": {\n          \"disable\": \"تعطيل\",\n          \"enable\": \"تفعيل\",\n          \"prefer\": \"مفضل\",\n          \"only\": \"فقط\"\n        },\n        \"routeRule\": {\n          \"title\": \"قواعد التوجيه\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"استيراد القواعد من الحافظة\",\n              \"file\": \"استيراد القواعد من ملف\"\n            },\n            \"export\": {\n              \"clipboard\": \"نسخ القواعد إلى الحافظة\",\n              \"file\": \"حفظ القواعد في ملف\"\n            },\n            \"reset\": \"إعادة تعيين القواعد\"\n          },\n          \"deleteRule\": \"حذف القاعدة\",\n          \"createRule\": \"إنشاء قاعدة جديدة\",\n          \"rule\": {\n            \"title\": \"قاعدة\",\n            \"ruleChanged\": \"تم تغيير القاعدة\",\n            \"ruleChangedMsg\": \"هل تريد حفظ تعديلاتك؟\",\n            \"onlyTunMode\": \"متوفر فقط في وضع TUN\",\n            \"notAvailabeInThisPlatform\": \"غير متوفر على هذا النظام\",\n            \"canNotBeEmpty\": \"لا يمكن أن يكون فارغًا\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"\\\"URL\\\" صالح مثل\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe or google chrome or chrome\",\n            \"validProcessName\": \"\\\"اسم العملية\\\" صالح مثل\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"\\\"مسار العملية\\\" صالح مثل\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 or 1-65000\",\n            \"validPortRange\": \"\\\"منفذ\\\" أو \\\"نطاق منافذ\\\" صالح مثل\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 or 10.0.0.0/24\",\n            \"validIpCidr\": \"IP CIDR صالح مثل\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com or dl.google.com\",\n            \"validDomain\": \"\\\"نطاق\\\" صالح مثل\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com or .ir\",\n            \"validDomainSuffix\": \"\\\"لاحقة نطاق\\\" صالحة مثل\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"الاسم\",\n              \"outbound\": \"التوجيه عند التطابق\",\n              \"rule_set\": \"رابط مجموعة القواعد\",\n              \"package_name\": \"أسماء الحزم\",\n              \"process_name\": \"أسماء العمليات\",\n              \"process_path\": \"مسارات العمليات\",\n              \"network\": \"الشبكات\",\n              \"port_range\": \"منافذ الوجهة\",\n              \"source_port_range\": \"منافذ المصدر\",\n              \"protocol\": \"البروتوكول\",\n              \"ip_cidr\": \"IP CIDR الوجهة\",\n              \"source_ip_cidr\": \"IP CIDR المصدر\",\n              \"domain\": \"النطاق\",\n              \"domain_suffixe\": \"لاحقة النطاق\",\n              \"domain_keyword\": \"كلمة مفتاحية للنطاق\",\n              \"domain_regex\": \"تعبير نمطي للنطاق\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"بروكسي\",\n              \"direct\": \"مباشر\",\n              \"direct_with_fragment\": \"مباشر مع Fragment\",\n              \"block\": \"حظر\"\n            },\n            \"network(map)\": {\n              \"all\": \"الكل\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"الكل\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"إضافة قيمة جديدة\",\n            \"update\": \"تحديث القيمة\",\n            \"clearList\": \"مسح القائمة\",\n            \"clearListMsg\": \"تم حذف جميع العناصر\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"تطبيقات أندرويد\",\n            \"showSystemApps\": \"عرض تطبيقات النظام\",\n            \"hideSystemApps\": \"إخفاء تطبيقات النظام\",\n            \"clearSelection\": \"مسح التحديد\",\n            \"uninstalled\": \"غير مثبت\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"DNS البعيد\",\n        \"remoteDnsDomainStrategy\": \"استراتيجية نطاق DNS البعيد\",\n        \"directDns\": \"محلل خادم الصادر (مباشر)\",\n        \"directDnsDomainStrategy\": \"استراتيجية النطاق الصادر\",\n        \"enableDnsRouting\": \"تمكين توجيه DNS\",\n        \"enableFakeDns\": \"تمكين DNS الوهمي\",\n        \"domainStrategy\": {\n          \"auto\": \"تلقائي\",\n          \"preferIpv6\": \"تفضيل IPv6\",\n          \"preferIpv4\": \"تفضيل IPv4\",\n          \"ipv4Only\": \"IPv4 فقط\",\n          \"ipv6Only\": \"IPv6 فقط\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"الوارد\",\n        \"serviceMode\": \"وضع الخدمة\",\n        \"serviceModes\": {\n          \"proxy\": \"خدمة البروكسي فقط\",\n          \"systemProxy\": \"تعيين بروكسي النظام\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"خدمة VPN\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"بروكسي\",\n          \"systemProxy\": \"بروكسي النظام\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"خدمة VPN\"\n        },\n        \"strictRoute\": \"توجيه صارم\",\n        \"tunImplementation\": \"تنفيذ Tun\",\n        \"tunImplementations\": {\n          \"mixed\": \"مختلط\",\n          \"system\": \"النظام\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"منفذ مختلط\",\n        \"tproxyPort\": \"منفذ البروكسي الشفاف\",\n        \"directPort\": \"منفذ مباشر\",\n        \"redirectPort\": \"منفذ إعادة التوجيه\",\n        \"allowConnectionFromLan\": \"مشاركة VPN على الشبكة المحلية\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"حيل TLS\",\n        \"enable\": \"تفعيل fragment\",\n        \"packets\": \"حزم التجزئة\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"حجم fragment\",\n        \"sleep\": \"تأخير fragment\",\n        \"mixedSniCase\": {\n          \"enable\": \"تفعيل الأحرف المختلطة لـ SNI\"\n        },\n        \"padding\": {\n          \"enable\": \"تفعيل padding\",\n          \"size\": \"حجم padding\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"تفعيل WARP\",\n        \"generateConfig\": \"إنشاء تكوين WARP\",\n        \"configGenerated\": \"تم إنشاء تكوين WARP\",\n        \"missingConfig\": \"تكوين WARP مفقود\",\n        \"detourMode\": \"وضع توجيه WARP\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"توجيه البروكسيات عبر WARP\",\n          \"warpOverProxy\": \"توجيه WARP عبر البروكسيات\",\n          \"proxyOverWarpExplain\": \"لإلغاء حظر البروكسيات بواسطة WARP\",\n          \"warpOverProxyExplain\": \"لأمان إضافي بواسطة WARP\"\n        },\n        \"licenseKey\": \"مفتاح الترخيص\",\n        \"cleanIp\": \"IP نظيف\",\n        \"port\": \"المنفذ\",\n        \"noise\": {\n          \"count\": \"عدد الضوضاء\",\n          \"mode\": \"وضع الضوضاء\",\n          \"size\": \"حجم الضوضاء\",\n          \"delay\": \"تأخير الضوضاء\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"الاتصال\",\n      \"traffic\": \"البيانات\",\n      \"trafficLive\": \"البيانات الحالية\",\n      \"trafficTotal\": \"إجمالي البيانات\",\n      \"uplink\": \"الإرسال\",\n      \"downlink\": \"الاستقبال\",\n      \"speed\": \"السرعة\",\n      \"totalTransferred\": \"إجمالي النقل\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"الرفع\",\n      \"download\": \"التنزيل\",\n      \"total\": \"إجمالي البيانات\",\n      \"expireDate\": \"تاريخ الانتهاء\",\n      \"expired\": \"منتهي الصلاحية\",\n      \"noTraffic\": \"نفدت الباقة\",\n      \"remainingTime\": \"الوقت المتبقي\",\n      \"remainingDuration\": \"متبقٍ ${duration} يوم\",\n      \"remainingDurationNew\": \"${duration} يوم\",\n      \"remainingTrafficSemanticLabel\": \"تم استهلاك ${consumed} من ${total}\",\n      \"remainingTraffic\": \"البيانات المتبقية\",\n      \"remainingUsage\": \"المتبقي\",\n      \"profileSite\": \"المزوّد\",\n      \"profileSupport\": \"الدعم\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"فرز حسب\",\n      \"sort\": {\n        \"name\": \"أبجديًا\",\n        \"lastUpdate\": \"آخر تحديث\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"موافقة Cloudflare WARP\",\n      \"description(rich)\": \"Cloudflare WARP هو مزود VPN مجاني لـ WireGuard. بتفعيل هذا الخيار، فإنك توافق على ${tos(شروط الخدمة)} و ${privacy(سياسة الخصوصية)} الخاصة بـ Cloudflare WARP.\"\n    },\n    \"newVersion\": {\n      \"title\": \"تحديث متاح\",\n      \"msg\": \"إصدار جديد من @:common.appTitle متاح. هل ترغب في التحديث الآن؟\",\n      \"currentVersion\": \"الإصدار الحالي: \",\n      \"newVersion\": \"الإصدار الجديد: \",\n      \"updateNow\": \"التحديث الآن\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"سيؤدي هذا إلى استبدال جميع إعداداتك الحالية. هل أنت متأكد؟\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"حذف الملف الشخصي\",\n          \"msg\": \"هل أنت متأكد من رغبتك في حذف هذا الملف الشخصي نهائيًا؟\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"تحسين الاختيار التلقائي\",\n          \"msg\": \"بمشاركة التطبيقات التي اخترتها، فإنك تساعد في إكمال قائمة \\\"الاختيار التلقائي\\\"\"\n        },\n        \"import\": {\n          \"msg\": \"سيؤدي هذا إلى استبدال جميع تحديداتك الحالية لبروكسي التطبيقات. هل أنت متأكد من رغبتك في المتابعة؟\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"حذف القاعدة\",\n          \"msg\": \"هل أنت متأكد من رغبتك في حذف قاعدة \\\"$rulename\\\"؟\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"ميزات تجريبية قيد الاستخدام\",\n      \"msg\": \"لقد فعّلت ميزات تجريبية قد تؤثر على جودة الاتصال وتسبب أخطاء غير متوقعة. يمكنك دائمًا تغيير هذه الخيارات أو إعادة تعيينها من صفحة الإعدادات.\",\n      \"disable\": \"لا تعرض مرة أخرى\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"اختر ملفًا شخصيًا\",\n      \"msg\": \"للبدء، قم بإضافة ملف اتصال يحتوي على تفاصيل اتصال VPN الخاصة بك.\\n\\nأليس لديك خادم VPN بعد؟ لا تقلق، اتبع الدليل أدناه لإعداد واحد بسرعة ومجانًا.\",\n      \"helpBtn\": {\n        \"label\": \"أرني كيف\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"تحذير من رابط خارجي\",\n      \"youAreAboutToVisit\": \"أنت على وشك زيارة:\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"هذا الموقع ليس ضمن قائمة المواقع الموثوقة لدينا. يرجى المتابعة بحذر.\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"العلامة الكاملة:\",\n      \"type\": \"النوع:\",\n      \"testTime\": \"وقت الاختبار:\",\n      \"testDelay\": \"تأخير الاختبار:\",\n      \"isSelected\": \"محدد:\",\n      \"isGroup\": \"مجموعة\",\n      \"isSecure\": \"آمن:\",\n      \"port\": \"المنفذ:\",\n      \"host\": \"المضيف:\",\n      \"ip\": \"IP:\",\n      \"countryCode\": \"رمز الدولة:\",\n      \"region\": \"المنطقة:\",\n      \"city\": \"المدينة:\",\n      \"asn\": \"ASN:\",\n      \"organization\": \"المُنظمة:\",\n      \"location\": \"الموقع:\",\n      \"postalCode\": \"الرمز البريدي:\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"السؤال كل مرة\",\n      \"alertMessage\": \"هل تريد إخفاء التطبيق أم الخروج منه؟\",\n      \"remember\": \"تذكر خياري\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"انقر للاتصال\",\n    \"connect\": \"اتصال\",\n    \"connecting\": \"جار الاتصال...\",\n    \"connected\": \"متصل\",\n    \"disconnect\": \"قطع الاتصال\",\n    \"disconnecting\": \"جاري قطع الاتصال...\",\n    \"reconnect\": \"إعادة الاتصال\",\n    \"reconnectMsg\": \"جاري إعادة الاتصال لتطبيق التغييرات...\",\n    \"secure\": \"مُؤمَّن بواسطة WARP\"\n  },\n  \"errors\": {\n    \"unexpected\": \"خطأ غير متوقع\",\n    \"connection\": {\n      \"unexpected\": \"خطأ اتصال غير متوقع\",\n      \"timeout\": \"انتهى وقت الاتصال\",\n      \"badResponse\": \"استجابة غير صالحة\",\n      \"connectionError\": \"خطأ في الاتصال\",\n      \"badCertificate\": \"شهادة غير صالحة\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"خطأ غير متوقع\",\n      \"notFound\": \"لم يتم العثور على الملف الشخصي\",\n      \"invalidConfig\": \"تكوينات غير صالحة\",\n      \"invalidUrl\": \"رابط غير صالح\",\n      \"canceledByUser\": \"تم الإلغاء من قبل المستخدم\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"فشل غير متوقع\",\n      \"missingVpnPermission\": \"إذن الـ VPN مفقود\",\n      \"missingNotificationPermission\": \"إذن الإشعارات مفقود\",\n      \"core\": \"خطأ في النواة\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"الخدمة لا تعمل\",\n      \"missingPrivilege\": \"صلاحيات مطلوبة\",\n      \"missingPrivilegeMsg\": \"وضع الـ VPN يتطلب صلاحيات المسؤول. يرجى إعادة تشغيل التطبيق كمسؤول أو تغيير وضع الخدمة.\",\n      \"invalidConfigOptions\": \"خيارات تكوين غير صالحة\",\n      \"invalidConfig\": \"تكوين غير صالح\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"رخصة WARP مفقودة\",\n      \"missingLicenseMsg\": \"الملف الشخصي المحدد يستخدم ميزة WARP. لاستخدام هذه الميزة، يجب الموافقة على شروط رخصة WARP.\"\n    }\n  }\n}"
  },
  {
    "path": "assets/translations/en.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"Hiddify\",\n    \"start\": \"Start\",\n    \"version\": \"Version\",\n    \"ok\": \"OK\",\n    \"cancel\": \"Cancel\",\n    \"kContinue\": \"Continue\",\n    \"showMore\": \"Show more\",\n    \"showLess\": \"Show less\",\n    \"filter\": \"Filter\",\n    \"all\": \"All\",\n    \"pause\": \"Pause\",\n    \"resume\": \"Resume\",\n    \"clear\": \"Clear\",\n    \"close\": \"Close\",\n    \"auto\": \"Auto\",\n    \"manually\": \"Manually\",\n    \"name\": \"Name\",\n    \"url\": \"URL\",\n    \"add\": \"Add\",\n    \"clipboard\": \"Clipboard\",\n    \"addToClipboard\": \"Add to clipboard\",\n    \"scanQr\": \"Scan QR\",\n    \"free\": \"Free\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Fragment\",\n    \"help\": \"Help\",\n    \"save\": \"Save\",\n    \"update\": \"Update\",\n    \"share\": \"Share\",\n    \"edit\": \"Edit\",\n    \"delete\": \"Delete\",\n    \"discard\": \"Discard\",\n    \"import\": \"Import\",\n    \"export\": \"Export\",\n    \"later\": \"Later\",\n    \"ignore\": \"Ignore\",\n    \"quit\": \"Quit\",\n    \"notSet\": \"Not set\",\n    \"hide\": \"Hide\",\n    \"exit\": \"Exit\",\n    \"reset\": \"Reset\",\n    \"done\": \"Done\",\n    \"search\": \"Search\",\n    \"decline\": \"Decline\",\n    \"agree\": \"Agree\",\n    \"empty\": \"Empty\",\n    \"unknown\": \"Unknown\",\n    \"hidden\": \"Hidden\",\n    \"timeout\": \"Timeout\",\n    \"sort\": \"Sort\",\n    \"dashboard\": \"Dashboard\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"$n day\",\n        \"other\": \"$n days\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"$n hour\",\n        \"other\": \"$n hours\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"Permission denied\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"Added to clipboard successfully\",\n          \"failure\": \"Failed to copy to clipboard\",\n          \"contentTooLarge\": \"Content too large. Use export file instead\"\n        },\n        \"file\": {\n          \"success\": \"JSON file created successfully\",\n          \"failure\": \"Failed to create file\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"Confirm import\",\n        \"success\": \"Imported successfully\",\n        \"failure\": \"Failed to import\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"All you need for an unrestricted internet\",\n    \"termsAndPolicyCaution(rich)\": \"By continuing you agree to ${tap(@:pages.about.termsAndConditions)}\",\n    \"info(rich)\": \"Made with ❤️ by Hiddify - ${tap_source(Open Source)} (${tap_license(License)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"Home\",\n      \"quickSettings\": \"Quick settings\"\n    },\n    \"proxies\": {\n      \"title\": \"Proxies\",\n      \"sort\": \"Sort proxies\",\n      \"testDelay\": \"Test delay\",\n      \"empty\": \"No proxies available\",\n      \"activeProxy\": \"Active proxy\",\n      \"unknownIp\": \"Unknown IP\",\n      \"sortOptions\": {\n        \"unsorted\": \"Default\",\n        \"name\": \"Alphabetically\",\n        \"delay\": \"By delay\",\n        \"usage\": \"By usage\"\n      },\n      \"ipInfo\": {\n        \"address\": \"IP address\",\n        \"country\": \"Country\",\n        \"organization\": \"Organization\"\n      },\n      \"delay\": {\n        \"result\": \"Delay: ${delay}ms\",\n        \"timeout\": \"Delay test timeout\",\n        \"testing\": \"Delay: testing...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"Profiles\",\n      \"add\": \"Add profile\",\n      \"update\": \"Update profile\",\n      \"viewAllProfiles\": \"View all profiles\",\n      \"activeProfileName\": \"Active profile name: \\\"${name}\\\".\",\n      \"nonActiveProfileName\": \"Select \\\"${name}\\\" as active profile\",\n      \"freeSubNotFound\": \"No free subscription was found\",\n      \"freeSubNotFoundForRegion\": \"No free subscription was found for \\\"${region}\\\" region.\",\n      \"failedToLoad\": \"Failed to load\",\n      \"updateSubscriptions\": \"Update subscriptions\",\n      \"share\": {\n        \"urlToClipboard\": \"URL to clipboard\",\n        \"showUrlQr\": \"Show URL QR\",\n        \"jsonToClipboard\": \"JSON to clipboard\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"Profile saved successfully\"\n        },\n        \"invalidUrl\": \"Invalid URL\",\n        \"add\": {\n          \"failure\": \"Failed to add profile\"\n        },\n        \"update\": {\n          \"success\": \"Profile updated successfully\",\n          \"successNamed\": \"\\\"${name}\\\" updated successfully\",\n          \"failure\": \"Failed to update profile\",\n          \"failureNamed\": \"Failed to update \\\"${name}\\\"\"\n        },\n        \"delete\": {\n          \"success\": \"Profile deleted successfully\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"Profile\",\n      \"lastUpdate\": \"Last update\",\n      \"form\": {\n        \"nameHint\": \"Profile name\",\n        \"emptyName\": \"Name is required\",\n        \"invalidUrl\": \"Invalid URL\",\n        \"urlHint\": \"Full config URL\",\n        \"disableAutoUpdate\": \"Disable auto update\",\n        \"autoUpdateInterval\": \"Auto update interval\",\n        \"loading\": \"Adding profile...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"Logs\",\n      \"shareCoreLogs\": \"Share core logs\",\n      \"shareAppLogs\": \"Share app logs\"\n    },\n    \"about\": {\n      \"title\": \"About\",\n      \"notAvailableMsg\": \"Already using the latest version\",\n      \"checkForUpdate\": \"Check for update\",\n      \"openWorkingDir\": \"Open working directory\",\n      \"sourceCode\": \"Source code\",\n      \"telegramChannel\": \"Telegram channel\",\n      \"termsAndConditions\": \"Terms and conditions\",\n      \"privacyPolicy\": \"Privacy policy\"\n    },\n    \"settings\": {\n      \"title\": \"Settings\",\n      \"resetTunnel\": \"Reset VPN profile\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"Import options from clipboard\",\n          \"file\": \"Import options from file\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"Copy anonymous options to clipboard\",\n          \"anonymousToFile\": \"Export anonymous options to file\",\n          \"allToClipboard\": \"Copy all options to clipboard\",\n          \"allToFile\": \"Export all options to file\"\n        },\n        \"reset\": \"Reset options\"\n      },\n      \"general\": {\n        \"title\": \"General\",\n        \"locale\": \"Language\",\n        \"themeMode\": \"Theme mode\",\n        \"themeModes\": {\n          \"system\": \"System default\",\n          \"dark\": \"Dark mode\",\n          \"light\": \"Light mode\",\n          \"black\": \"Black mode\"\n        },\n        \"enableAnalytics\": \"Enable analytics\",\n        \"enableAnalyticsMsg\": \"Give permission to collect analytics and send crash reports to improve the app\",\n        \"autoIpCheck\": \"Automatically check connection IP\",\n        \"dynamicNotification\": \"Display speed in notification\",\n        \"hapticFeedback\": \"Haptic feedback\",\n        \"actionAtClosing\": \"Action at closing\",\n        \"autoStart\": \"Start at login\",\n        \"silentStart\": \"Start minimized\",\n        \"ignoreBatteryOptimizations\": \"Disable battery optimization\",\n        \"ignoreBatteryOptimizationsMsg\": \"Remove restrictions for optimal VPN performance\",\n        \"memoryLimit\": \"Memory limit\",\n        \"memoryLimitMsg\": \"Enable if you're experiencing out of memory errors or frequent app crashes\",\n        \"debugMode\": \"Debug mode\",\n        \"debugModeMsg\": \"Restart the app for applying this change\",\n        \"logLevel\": \"Log level\",\n        \"connectionTestUrl\": \"Connection test URL\",\n        \"urlTestInterval\": \"URL test interval\",\n        \"clashApiPort\": \"Clash API port\",\n        \"useXrayCoreWhenPossible\": \"Use xray-core when possible\",\n        \"useXrayCoreWhenPossibleMsg\": \"Use xray-core during parsing sub links. You need to reimport the sub link to enable this option.\"\n      },\n      \"routing\": {\n        \"title\": \"Routing\",\n        \"perAppProxy\": {\n          \"title\": \"Per-app proxy\",\n          \"hideSysApps\": \"Hide system apps\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Import selection from clipboard\",\n              \"file\": \"Import selection from file\",\n              \"msg\": \"Importing will replace your current selections. Are you sure you want to continue?\"\n            },\n            \"export\": {\n              \"clipboard\": \"Copy selection to clipboard\",\n              \"file\": \"Export selection to file\"\n            },\n            \"shareToAll\": \"Share to all\",\n            \"clearAllSelections\": \"Clear all selections\"\n          },\n          \"modes\": {\n            \"all\": \"All\",\n            \"proxy\": \"Proxy\",\n            \"bypass\": \"Bypass\",\n            \"allMsg\": \"Proxy all apps\",\n            \"proxyMsg\": \"Proxy only selected apps\",\n            \"bypassMsg\": \"Do not proxy selected apps\"\n          },\n          \"autoSelection\": {\n            \"title\": \"Auto selection\",\n            \"performNow\": \"Perform now\",\n            \"resetToDefault\": \"Reset to default\",\n            \"autoUpdateInterval\": \"Auto update interval\",\n            \"toast\": {\n              \"success\": \"Auto apps selection completed successfully\",\n              \"failure\": \"Auto selection failed\",\n              \"regionNotFound\": \"Auto selection not found, region \\\"${region}\\\"\",\n              \"alreadyInAuto\": \"Your selections are already in the auto-list\"\n            },\n            \"dialog\": {\n              \"title\": \"Auto apps selection\",\n              \"msg\": \"The auto selection feature for per-app proxy was disabled due to the region change to \\\"${region}\\\"\"\n            }\n          }\n        },\n        \"region\": \"Region\",\n        \"regions\": {\n          \"ir\": \"Iran (ir)\",\n          \"cn\": \"China (cn)\",\n          \"ru\": \"Russia (ru)\",\n          \"af\": \"Afghanistan (af)\",\n          \"id\": \"Indonesia (id)\",\n          \"tr\": \"Türkiye (tr)\",\n          \"br\": \"Brazil (br)\",\n          \"other\": \"Other\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"Balancer strategy\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"Block advertisements\",\n        \"bypassLan\": \"Bypass LAN\",\n        \"resolveDestination\": \"Resolve destination\",\n        \"ipv6Route\": \"IPv6 route\",\n        \"ipv6Modes\": {\n          \"disable\": \"Disable\",\n          \"enable\": \"Enable\",\n          \"prefer\": \"Preferred\",\n          \"only\": \"Exclusive\"\n        },\n        \"routeRule\": {\n          \"title\": \"Route rules\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Import rules from clipboard\",\n              \"file\": \"Import rules from file\"\n            },\n            \"export\": {\n              \"clipboard\": \"Copy rules to clipboard\",\n              \"file\": \"Save rules to file\"\n            },\n            \"reset\": \"Reset rules\"\n          },\n          \"deleteRule\": \"Delete rule\",\n          \"createRule\": \"Create new rule\",\n          \"rule\": {\n            \"title\": \"Rule\",\n            \"ruleChanged\": \"Rule changed\",\n            \"ruleChangedMsg\": \"Do you want to save your edits?\",\n            \"onlyTunMode\": \"Available only in tun mode\",\n            \"notAvailabeInThisPlatform\": \"Not available in this platform\",\n            \"canNotBeEmpty\": \"Can not be empty\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"Valid \\\"URL\\\" like\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe or google chrome or chrome\",\n            \"validProcessName\": \"Valid \\\"Process Name\\\" like\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"Valid \\\"Process Path\\\" like\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 or 1-65000\",\n            \"validPortRange\": \"Valid \\\"Port\\\" or \\\"Port Range\\\" like\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 or 10.0.0.0/24\",\n            \"validIpCidr\": \"Valid IP CIDR like\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com or dl.google.com\",\n            \"validDomain\": \"Valid \\\"Domain\\\" like\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com or .ir\",\n            \"validDomainSuffix\": \"Valid \\\"Domain Suffix\\\" like\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"Name\",\n              \"outbound\": \"Outbound if match\",\n              \"rule_set\": \"Rule set URL\",\n              \"package_name\": \"Package names\",\n              \"process_name\": \"Process names\",\n              \"process_path\": \"Process paths\",\n              \"network\": \"Networks\",\n              \"port_range\": \"Destination ports\",\n              \"source_port_range\": \"Source ports\",\n              \"protocol\": \"Protocol\",\n              \"ip_cidr\": \"Destination IP CIDR\",\n              \"source_ip_cidr\": \"Source IP CIDR\",\n              \"domain\": \"Domain\",\n              \"domain_suffixe\": \"Domain suffix\",\n              \"domain_keyword\": \"Domain keyword\",\n              \"domain_regex\": \"Domain regex\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"Proxy\",\n              \"direct\": \"Direct\",\n              \"direct_with_fragment\": \"Direct with fragment\",\n              \"block\": \"Block\"\n            },\n            \"network(map)\": {\n              \"all\": \"All\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"All\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"Add new value\",\n            \"update\": \"Update value\",\n            \"clearList\": \"Clear list\",\n            \"clearListMsg\": \"All items are deleted\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"Android apps\",\n            \"showSystemApps\": \"Show system apps\",\n            \"hideSystemApps\": \"Hide system apps\",\n            \"clearSelection\": \"Clear selection\",\n            \"uninstalled\": \"Uninstalled\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"Remote DNS\",\n        \"remoteDnsDomainStrategy\": \"Remote DNS domain strategy\",\n        \"directDns\": \"Outbound server resolver (direct)\",\n        \"directDnsDomainStrategy\": \"Outbound domain strategy\",\n        \"enableDnsRouting\": \"Enable DNS routing\",\n        \"enableFakeDns\": \"Enable fake DNS\",\n        \"domainStrategy\": {\n          \"auto\": \"Auto\",\n          \"preferIpv6\": \"Prefer IPv6\",\n          \"preferIpv4\": \"Prefer IPv4\",\n          \"ipv4Only\": \"IPv4 only\",\n          \"ipv6Only\": \"IPv6 only\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"Inbound\",\n        \"serviceMode\": \"Service mode\",\n        \"serviceModes\": {\n          \"proxy\": \"Proxy service only\",\n          \"systemProxy\": \"Set system proxy\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"VPN service\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"Proxy\",\n          \"systemProxy\": \"System proxy\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"VPN service\"\n        },\n        \"strictRoute\": \"Strict route\",\n        \"tunImplementation\": \"Tun implementation\",\n        \"tunImplementations\": {\n          \"mixed\": \"Mixed\",\n          \"system\": \"System\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"Mixed port\",\n        \"tproxyPort\": \"Transparent proxy port\",\n        \"directPort\": \"Direct port\",\n        \"redirectPort\": \"Redirect port\",\n        \"allowConnectionFromLan\": \"Share VPN in local network\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"TLS tricks\",\n        \"enable\": \"Enable fragment\",\n        \"packets\": \"Fragmentation Packets\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"Fragment size\",\n        \"sleep\": \"Fragment sleep\",\n        \"mixedSniCase\": {\n          \"enable\": \"Enable mixed SNI case\"\n        },\n        \"padding\": {\n          \"enable\": \"Enable padding\",\n          \"size\": \"Padding size\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"Enable WARP\",\n        \"generateConfig\": \"Generate WARP config\",\n        \"configGenerated\": \"Warp config is generated\",\n        \"missingConfig\": \"Missing WARP config\",\n        \"detourMode\": \"Detour mode\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"Detour proxies through WARP \",\n          \"warpOverProxy\": \"Detour WARP through proxies\",\n          \"proxyOverWarpExplain\": \"Unblock proxies by WARP\",\n          \"warpOverProxyExplain\": \"Extra security by WARP\"\n        },\n        \"licenseKey\": \"License key\",\n        \"cleanIp\": \"Clean IP\",\n        \"port\": \"Port\",\n        \"noise\": {\n          \"count\": \"Noise count\",\n          \"mode\": \"Noise mode\",\n          \"size\": \"Noise size\",\n          \"delay\": \"Noise delay\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"Connection\",\n      \"traffic\": \"Traffic\",\n      \"trafficLive\": \"Live traffic\",\n      \"trafficTotal\": \"Total traffic\",\n      \"uplink\": \"Uplink\",\n      \"downlink\": \"Downlink\",\n      \"speed\": \"Speed\",\n      \"totalTransferred\": \"Total transferred\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"Upload\",\n      \"download\": \"Download\",\n      \"total\": \"Total traffic\",\n      \"expireDate\": \"Expire date\",\n      \"expired\": \"Expired\",\n      \"noTraffic\": \"Out of quota\",\n      \"remainingTime\": \"Remaining time\",\n      \"remainingDuration\": \"${duration} days remaining\",\n      \"remainingDurationNew\": \"${duration} days\",\n      \"remainingTrafficSemanticLabel\": \"${consumed} of ${total} traffic consumed\",\n      \"remainingTraffic\": \"Remaining traffic\",\n      \"remainingUsage\": \"Remaining\",\n      \"profileSite\": \"Provider\",\n      \"profileSupport\": \"Support\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"Sort by\",\n      \"sort\": {\n        \"name\": \"Alphabetically\",\n        \"lastUpdate\": \"Recently updated\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"Cloudflare WARP consent\",\n      \"description(rich)\": \"Cloudflare WARP is a free WireGuard VPN provider. By enabling this option you are agreeing to the Cloudflare WARP's ${tos(Terms of service)} and ${privacy(Privacy policy)}.\"\n    },\n    \"newVersion\": {\n      \"title\": \"Update available\",\n      \"msg\": \"A new version of @:common.appTitle is available. Would you like to update now?\",\n      \"currentVersion\": \"Current version: \",\n      \"newVersion\": \"New version: \",\n      \"updateNow\": \"Update now\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"This will rewrite all config options with provided values. Are you sure?\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"Delete profile\",\n          \"msg\": \"Are you sure you want to permanently delete this profile?\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"Improving auto selection\",\n          \"msg\": \"By sharing selected apps, you help complete the \\\"auto selection\\\" list\"\n        },\n        \"import\": {\n          \"msg\": \"This will replace all your current per-app proxy selections. Are you sure you want to continue?\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"Delete rule\",\n          \"msg\": \"Are you sure you want to delete the \\\"$rulename\\\" rule?\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"Experimental features in use\",\n      \"msg\": \"You've enabled some experimental features which might affect connection quality and cause unexpected errors. You can always change or reset these options from config options page.\",\n      \"disable\": \"Don't show again\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"Choose a profile\",\n      \"msg\": \"Let's get started by adding a connection profile that includes your VPN connection details.\\n\\nDon’t have a VPN server yet? No worries—just follow the tutorial below to set one up quickly and for free.\",\n      \"helpBtn\": {\n        \"label\": \"Show me how\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"External link warning\",\n      \"youAreAboutToVisit\": \"You are about to visit :\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"This website is not in our trusted list. Please proceed with caution.\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"Full tag:\",\n      \"type\": \"Type:\",\n      \"testTime\": \"Test time:\",\n      \"testDelay\": \"Test delay:\",\n      \"isSelected\": \"Is selected:\",\n      \"isGroup\": \"Is group\",\n      \"isSecure\": \"Is secure:\",\n      \"port\": \"Port:\",\n      \"host\": \"Host:\",\n      \"ip\": \"IP:\",\n      \"countryCode\": \"Country code:\",\n      \"region\": \"Region:\",\n      \"city\": \"City:\",\n      \"asn\": \"ASN:\",\n      \"organization\": \"Organization:\",\n      \"location\": \"Location:\",\n      \"postalCode\": \"Postal code:\",\n      \"download\": \"Download:\",\n      \"upload\": \"Upload:\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"Ask each time\",\n      \"alertMessage\": \"Hide or exit the application?\",\n      \"remember\": \"Remember my choice\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"Tap to connect\",\n    \"connect\": \"Connect\",\n    \"connecting\": \"Connecting...\",\n    \"connected\": \"Connected\",\n    \"disconnect\": \"Disconnect\",\n    \"disconnecting\": \"Disconnecting...\",\n    \"reconnect\": \"Reconnect\",\n    \"reconnectMsg\": \"Reconnecting for taking into account the changes...\",\n    \"secure\": \"Secured by WARP\"\n  },\n  \"errors\": {\n    \"unexpected\": \"Unexpected error\",\n    \"connection\": {\n      \"unexpected\": \"Unexpected connection error\",\n      \"timeout\": \"Connection timeout\",\n      \"badResponse\": \"Bad response\",\n      \"connectionError\": \"Connection error\",\n      \"badCertificate\": \"Bad certificate\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"Unexpected error\",\n      \"notFound\": \"Profile not found\",\n      \"invalidConfig\": \"Invalid configs\",\n      \"invalidUrl\": \"Invalid URL\",\n      \"canceledByUser\": \"Canceled by user\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"Unexpected failure\",\n      \"missingVpnPermission\": \"Missing VPN permission\",\n      \"missingNotificationPermission\": \"Missing notification permission\",\n      \"core\": \"Core error\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"Service is not running\",\n      \"missingPrivilege\": \"Missing privilege\",\n      \"missingPrivilegeMsg\": \"VPN mode requires administrator privileges. Either relaunch the app as administrator or change service mode.\",\n      \"invalidConfigOptions\": \"Invalid configuration options\",\n      \"invalidConfig\": \"Invalid configuration\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"Warp license\",\n      \"missingLicenseMsg\": \"The selected profile uses the WARP feature; to use this feature, the WARP license must be agreed to.\"\n    }\n  }\n}"
  },
  {
    "path": "assets/translations/es.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"Hiddify\",\n    \"start\": \"Comenzar\",\n    \"version\": \"Versión\",\n    \"ok\": \"Aceptar\",\n    \"cancel\": \"Cancelar\",\n    \"kContinue\": \"Continuar\",\n    \"showMore\": \"Mostrar más\",\n    \"showLess\": \"Mostrar menos\",\n    \"filter\": \"Filtrar\",\n    \"all\": \"Todos\",\n    \"pause\": \"Pausar\",\n    \"resume\": \"Reanudar\",\n    \"clear\": \"Limpiar\",\n    \"close\": \"Cerrar\",\n    \"auto\": \"Automático\",\n    \"manually\": \"Manualmente\",\n    \"name\": \"Nombre\",\n    \"url\": \"URL\",\n    \"add\": \"Añadir\",\n    \"clipboard\": \"Portapapeles\",\n    \"addToClipboard\": \"Añadir al portapapeles\",\n    \"scanQr\": \"Escanear QR\",\n    \"free\": \"Gratis\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Fragmento\",\n    \"help\": \"Ayuda\",\n    \"save\": \"Guardar\",\n    \"update\": \"Actualizar\",\n    \"share\": \"Compartir\",\n    \"edit\": \"Editar\",\n    \"delete\": \"Eliminar\",\n    \"discard\": \"Descartar\",\n    \"import\": \"Importar\",\n    \"export\": \"Exportar\",\n    \"later\": \"Más tarde\",\n    \"ignore\": \"Ignorar\",\n    \"quit\": \"Salir\",\n    \"notSet\": \"No establecido\",\n    \"hide\": \"Ocultar\",\n    \"exit\": \"Salir\",\n    \"reset\": \"Restablecer\",\n    \"done\": \"Hecho\",\n    \"search\": \"Buscar\",\n    \"decline\": \"Rechazar\",\n    \"agree\": \"Aceptar\",\n    \"empty\": \"Vacío\",\n    \"unknown\": \"Desconocido\",\n    \"hidden\": \"Oculto\",\n    \"timeout\": \"Tiempo agotado\",\n    \"sort\": \"Ordenar\",\n    \"dashboard\": \"Panel\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"$n día\",\n        \"other\": \"$n días\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"$n hora\",\n        \"other\": \"$n horas\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"Permiso denegado\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"Añadido al portapapeles con éxito\",\n          \"failure\": \"Error al copiar al portapapeles\",\n          \"contentTooLarge\": \"Contenido demasiado grande. Use la exportación a archivo en su lugar\"\n        },\n        \"file\": {\n          \"success\": \"Archivo JSON creado con éxito\",\n          \"failure\": \"Error al crear el archivo\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"Confirmar importación\",\n        \"success\": \"Importado con éxito\",\n        \"failure\": \"Error al importar\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"Todo lo que necesitas para un internet sin restricciones\",\n    \"termsAndPolicyCaution(rich)\": \"Al continuar, aceptas los ${tap(@:pages.about.termsAndConditions)}\",\n    \"info(rich)\": \"Hecho con ❤️ por Hiddify - ${tap_source(Código Abierto)} (${tap_license(Licencia)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"Inicio\",\n      \"quickSettings\": \"Ajustes rápidos\"\n    },\n    \"proxies\": {\n      \"title\": \"Proxies\",\n      \"sort\": \"Ordenar proxies\",\n      \"testDelay\": \"Probar latencia\",\n      \"empty\": \"No hay proxies disponibles\",\n      \"activeProxy\": \"Proxy activo\",\n      \"unknownIp\": \"IP desconocida\",\n      \"sortOptions\": {\n        \"unsorted\": \"Por defecto\",\n        \"name\": \"Alfabéticamente\",\n        \"delay\": \"Por latencia\"\n      },\n      \"ipInfo\": {\n        \"address\": \"Dirección IP\",\n        \"country\": \"País\",\n        \"organization\": \"Organización\"\n      },\n      \"delay\": {\n        \"result\": \"Latencia: ${delay}ms\",\n        \"timeout\": \"Tiempo de prueba de latencia agotado\",\n        \"testing\": \"Latencia: probando...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"Perfiles\",\n      \"add\": \"Añadir perfil\",\n      \"update\": \"Actualizar perfil\",\n      \"viewAllProfiles\": \"Ver todos los perfiles\",\n      \"activeProfileName\": \"Nombre del perfil activo: \\\"${name}\\\".\",\n      \"nonActiveProfileName\": \"Seleccionar \\\"${name}\\\" como perfil activo\",\n      \"freeSubNotFound\": \"No se encontró ninguna suscripción gratuita\",\n      \"freeSubNotFoundForRegion\": \"No se encontró ninguna suscripción gratuita para la región \\\"${region}\\\"\",\n      \"failedToLoad\": \"Error al cargar\",\n      \"updateSubscriptions\": \"Actualizar suscripciones\",\n      \"share\": {\n        \"urlToClipboard\": \"URL al portapapeles\",\n        \"showUrlQr\": \"Mostrar QR de la URL\",\n        \"jsonToClipboard\": \"JSON al portapapeles\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"Perfil guardado con éxito\"\n        },\n        \"invalidUrl\": \"URL no válida\",\n        \"add\": {\n          \"failure\": \"Error al añadir el perfil\"\n        },\n        \"update\": {\n          \"success\": \"Perfil actualizado con éxito\",\n          \"successNamed\": \"\\\"${name}\\\" actualizado con éxito\",\n          \"failure\": \"Error al actualizar el perfil\",\n          \"failureNamed\": \"Error al actualizar \\\"${name}\\\"\"\n        },\n        \"delete\": {\n          \"success\": \"Perfil eliminado con éxito\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"Perfil\",\n      \"lastUpdate\": \"Última actualización\",\n      \"form\": {\n        \"nameHint\": \"Nombre del perfil\",\n        \"emptyName\": \"El nombre es obligatorio\",\n        \"invalidUrl\": \"URL no válida\",\n        \"urlHint\": \"URL de configuración completa\",\n        \"disableAutoUpdate\": \"Desactivar actualización automática\",\n        \"autoUpdateInterval\": \"Intervalo de actualización automática\",\n        \"loading\": \"Añadiendo perfil...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"Registros\",\n      \"shareCoreLogs\": \"Compartir registros del núcleo\",\n      \"shareAppLogs\": \"Compartir registros de la aplicación\"\n    },\n    \"about\": {\n      \"title\": \"Acerca de\",\n      \"notAvailableMsg\": \"Ya estás usando la última versión\",\n      \"checkForUpdate\": \"Buscar actualizaciones\",\n      \"openWorkingDir\": \"Abrir directorio de trabajo\",\n      \"sourceCode\": \"Código fuente\",\n      \"telegramChannel\": \"Canal de Telegram\",\n      \"termsAndConditions\": \"Términos y condiciones\",\n      \"privacyPolicy\": \"Política de privacidad\"\n    },\n    \"settings\": {\n      \"title\": \"Ajustes\",\n      \"resetTunnel\": \"Restablecer perfil de VPN\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"Importar opciones desde el portapapeles\",\n          \"file\": \"Importar opciones desde un archivo\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"Copiar opciones anónimas al portapapeles\",\n          \"anonymousToFile\": \"Exportar opciones anónimas a un archivo\",\n          \"allToClipboard\": \"Copiar todas las opciones al portapapeles\",\n          \"allToFile\": \"Exportar todas las opciones a un archivo\"\n        },\n        \"reset\": \"Restablecer opciones\"\n      },\n      \"general\": {\n        \"title\": \"General\",\n        \"locale\": \"Idioma\",\n        \"themeMode\": \"Tema\",\n        \"themeModes\": {\n          \"system\": \"Por defecto del sistema\",\n          \"dark\": \"Modo oscuro\",\n          \"light\": \"Modo claro\",\n          \"black\": \"Modo negro\"\n        },\n        \"enableAnalytics\": \"Habilitar análisis\",\n        \"enableAnalyticsMsg\": \"Dar permiso para recopilar análisis y enviar informes de fallos para mejorar la aplicación\",\n        \"autoIpCheck\": \"Comprobar IP de conexión automáticamente\",\n        \"dynamicNotification\": \"Mostrar velocidad en la notificación\",\n        \"hapticFeedback\": \"Respuesta háptica\",\n        \"actionAtClosing\": \"Acción al cerrar\",\n        \"autoStart\": \"Iniciar al arrancar\",\n        \"silentStart\": \"Iniciar minimizado\",\n        \"ignoreBatteryOptimizations\": \"Desactivar optimización de batería\",\n        \"ignoreBatteryOptimizationsMsg\": \"Eliminar restricciones para un rendimiento óptimo de la VPN\",\n        \"memoryLimit\": \"Límite de memoria\",\n        \"memoryLimitMsg\": \"Habilitar si experimentas errores de falta de memoria o fallos frecuentes de la aplicación\",\n        \"debugMode\": \"Modo de depuración\",\n        \"debugModeMsg\": \"Reinicia la aplicación para aplicar este cambio\",\n        \"logLevel\": \"Nivel de registro\",\n        \"connectionTestUrl\": \"URL de prueba de conexión\",\n        \"urlTestInterval\": \"Intervalo de prueba de URL\",\n        \"clashApiPort\": \"Puerto de la API de Clash\",\n        \"useXrayCoreWhenPossible\": \"Usar xray-core cuando sea posible\",\n        \"useXrayCoreWhenPossibleMsg\": \"Usa xray-core al analizar enlaces de suscripción. Necesitas reimportar el enlace para habilitar esta opción\"\n      },\n      \"routing\": {\n        \"title\": \"Enrutamiento\",\n        \"perAppProxy\": {\n          \"title\": \"Proxy por aplicación\",\n          \"hideSysApps\": \"Ocultar aplicaciones del sistema\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Importar selección desde el portapapeles\",\n              \"file\": \"Importar selección desde un archivo\",\n              \"msg\": \"La importación reemplazará tus selecciones actuales. ¿Estás seguro de que quieres continuar?\"\n            },\n            \"export\": {\n              \"clipboard\": \"Copiar selección al portapapeles\",\n              \"file\": \"Exportar selección a un archivo\"\n            },\n            \"shareToAll\": \"Compartir con todos\",\n            \"clearAllSelections\": \"Borrar todas las selecciones\"\n          },\n          \"modes\": {\n            \"all\": \"Todo\",\n            \"proxy\": \"Proxy\",\n            \"bypass\": \"Omitir\",\n            \"allMsg\": \"Usar proxy en todas las aplicaciones\",\n            \"proxyMsg\": \"Usar proxy solo en aplicaciones seleccionadas\",\n            \"bypassMsg\": \"No usar proxy en aplicaciones seleccionadas\"\n          },\n          \"autoSelection\": {\n            \"title\": \"Selección automática\",\n            \"performNow\": \"Ejecutar ahora\",\n            \"resetToDefault\": \"Restablecer por defecto\",\n            \"autoUpdateInterval\": \"Intervalo de actualización automática\",\n            \"toast\": {\n              \"success\": \"Selección automática de aplicaciones completada con éxito\",\n              \"failure\": \"Fallo en la selección automática\",\n              \"regionNotFound\": \"No se encontró selección automática para la región \\\"${region}\\\"\",\n              \"alreadyInAuto\": \"Tus selecciones ya están en la lista automática\"\n            },\n            \"dialog\": {\n              \"title\": \"Selección automática de aplicaciones\",\n              \"msg\": \"La función de selección automática para el proxy por aplicación se ha desactivado debido al cambio de región a \\\"${region}\\\"\"\n            }\n          }\n        },\n        \"region\": \"Región\",\n        \"regions\": {\n          \"ir\": \"Irán (ir)\",\n          \"cn\": \"China (cn)\",\n          \"ru\": \"Rusia (ru)\",\n          \"af\": \"Afganistán (af)\",\n          \"id\": \"Indonesia (id)\",\n          \"tr\": \"Turquía (tr)\",\n          \"br\": \"Brasil (br)\",\n          \"other\": \"Otro\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"Estrategia de Balancer\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"Bloquear anuncios\",\n        \"bypassLan\": \"Omitir LAN\",\n        \"resolveDestination\": \"Resolver destino\",\n        \"ipv6Route\": \"Ruta IPv6\",\n        \"ipv6Modes\": {\n          \"disable\": \"Desactivar\",\n          \"enable\": \"Activar\",\n          \"prefer\": \"Preferido\",\n          \"only\": \"Exclusivo\"\n        },\n        \"routeRule\": {\n          \"title\": \"Reglas de enrutamiento\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Importar reglas desde el portapapeles\",\n              \"file\": \"Importar reglas desde un archivo\"\n            },\n            \"export\": {\n              \"clipboard\": \"Copiar reglas al portapapeles\",\n              \"file\": \"Guardar reglas en un archivo\"\n            },\n            \"reset\": \"Restablecer reglas\"\n          },\n          \"deleteRule\": \"Eliminar regla\",\n          \"createRule\": \"Crear nueva regla\",\n          \"rule\": {\n            \"title\": \"Regla\",\n            \"ruleChanged\": \"Regla modificada\",\n            \"ruleChangedMsg\": \"¿Quieres guardar tus cambios?\",\n            \"onlyTunMode\": \"Disponible solo en modo TUN\",\n            \"notAvailabeInThisPlatform\": \"No disponible en esta plataforma\",\n            \"canNotBeEmpty\": \"No puede estar vacío\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"\\\"URL\\\" válida como\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe or google chrome or chrome\",\n            \"validProcessName\": \"\\\"Nombre de proceso\\\" válido como\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"\\\"Ruta de proceso\\\" válida como\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 or 1-65000\",\n            \"validPortRange\": \"\\\"Puerto\\\" o \\\"Rango de puertos\\\" válido como\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 or 10.0.0.0/24\",\n            \"validIpCidr\": \"IP CIDR válido como\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com or dl.google.com\",\n            \"validDomain\": \"\\\"Dominio\\\" válido como\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com or .ir\",\n            \"validDomainSuffix\": \"\\\"Sufijo de dominio\\\" válido como\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"Nombre\",\n              \"outbound\": \"Salida si coincide\",\n              \"rule_set\": \"URL del conjunto de reglas\",\n              \"package_name\": \"Nombres de paquetes\",\n              \"process_name\": \"Nombres de procesos\",\n              \"process_path\": \"Rutas de procesos\",\n              \"network\": \"Redes\",\n              \"port_range\": \"Puertos de destino\",\n              \"source_port_range\": \"Puertos de origen\",\n              \"protocol\": \"Protocolo\",\n              \"ip_cidr\": \"IP CIDR de destino\",\n              \"source_ip_cidr\": \"IP CIDR de origen\",\n              \"domain\": \"Dominio\",\n              \"domain_suffixe\": \"Sufijo de dominio\",\n              \"domain_keyword\": \"Palabra clave de dominio\",\n              \"domain_regex\": \"Expresión regular de dominio\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"Proxy\",\n              \"direct\": \"Directo\",\n              \"direct_with_fragment\": \"Directo con fragmento\",\n              \"block\": \"Bloquear\"\n            },\n            \"network(map)\": {\n              \"all\": \"Todo\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"Todos\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"Añadir nuevo valor\",\n            \"update\": \"Actualizar valor\",\n            \"clearList\": \"Limpiar lista\",\n            \"clearListMsg\": \"Todos los elementos han sido eliminados\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"Aplicaciones de Android\",\n            \"showSystemApps\": \"Mostrar aplicaciones del sistema\",\n            \"hideSystemApps\": \"Ocultar aplicaciones del sistema\",\n            \"clearSelection\": \"Borrar selección\",\n            \"uninstalled\": \"Desinstalado\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"DNS remoto\",\n        \"remoteDnsDomainStrategy\": \"Estrategia de dominio de DNS remoto\",\n        \"directDns\": \"Resolución del servidor de salida (directo)\",\n        \"directDnsDomainStrategy\": \"Estrategia de dominio de salida\",\n        \"enableDnsRouting\": \"Habilitar enrutamiento de DNS\",\n        \"enableFakeDns\": \"Habilitar DNS falso\",\n        \"domainStrategy\": {\n          \"auto\": \"Automático\",\n          \"preferIpv6\": \"Preferir IPv6\",\n          \"preferIpv4\": \"Preferir IPv4\",\n          \"ipv4Only\": \"Solo IPv4\",\n          \"ipv6Only\": \"Solo IPv6\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"Entrada\",\n        \"serviceMode\": \"Modo de servicio\",\n        \"serviceModes\": {\n          \"proxy\": \"Solo servicio de proxy\",\n          \"systemProxy\": \"Establecer proxy del sistema\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"Servicio VPN\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"Proxy\",\n          \"systemProxy\": \"Proxy del sistema\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"Servicio VPN\"\n        },\n        \"strictRoute\": \"Ruta estricta\",\n        \"tunImplementation\": \"Implementación de TUN\",\n        \"tunImplementations\": {\n          \"mixed\": \"Mixto\",\n          \"system\": \"Sistema\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"Puerto mixto\",\n        \"tproxyPort\": \"Puerto de proxy transparente\",\n        \"directPort\": \"Puerto de Directo\",\n        \"redirectPort\": \"Puerto de redirección\",\n        \"allowConnectionFromLan\": \"Compartir VPN en la red local\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"Trucos de TLS\",\n        \"enable\": \"Habilitar fragmento\",\n        \"packets\": \"Paquetes de fragmentación\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"Tamaño de fragmento\",\n        \"sleep\": \"Retraso de fragmento\",\n        \"mixedSniCase\": {\n          \"enable\": \"Habilitar mayúsculas/minúsculas mixtas en SNI\"\n        },\n        \"padding\": {\n          \"enable\": \"Habilitar relleno\",\n          \"size\": \"Tamaño de relleno\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"Habilitar WARP\",\n        \"generateConfig\": \"Generar configuración de WARP\",\n        \"configGenerated\": \"Configuración de WARP generada\",\n        \"missingConfig\": \"Falta la configuración de WARP\",\n        \"detourMode\": \"Modo de desvío\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"Desviar proxies a través de WARP\",\n          \"warpOverProxy\": \"Desviar WARP a través de proxies\",\n          \"proxyOverWarpExplain\": \"Desbloquear proxies con WARP\",\n          \"warpOverProxyExplain\": \"Seguridad extra con WARP\"\n        },\n        \"licenseKey\": \"Clave de licencia\",\n        \"cleanIp\": \"IP limpia\",\n        \"port\": \"Puerto\",\n        \"noise\": {\n          \"count\": \"Cantidad de ruido\",\n          \"mode\": \"Modo de ruido\",\n          \"size\": \"Tamaño de ruido\",\n          \"delay\": \"Retraso de ruido\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"Conexión\",\n      \"traffic\": \"Tráfico\",\n      \"trafficLive\": \"Tráfico en tiempo real\",\n      \"trafficTotal\": \"Tráfico total\",\n      \"uplink\": \"Subida\",\n      \"downlink\": \"Bajada\",\n      \"speed\": \"Velocidad\",\n      \"totalTransferred\": \"Total transferido\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"Subida\",\n      \"download\": \"Descarga\",\n      \"total\": \"Tráfico total\",\n      \"expireDate\": \"Fecha de caducidad\",\n      \"expired\": \"Caducado\",\n      \"noTraffic\": \"Cuota agotada\",\n      \"remainingTime\": \"Tiempo restante\",\n      \"remainingDuration\": \"${duration} días restantes\",\n      \"remainingDurationNew\": \"${duration} días\",\n      \"remainingTrafficSemanticLabel\": \"${consumed} de ${total} de tráfico consumido\",\n      \"remainingTraffic\": \"Tráfico restante\",\n      \"remainingUsage\": \"Restante\",\n      \"profileSite\": \"Proveedor\",\n      \"profileSupport\": \"Soporte\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"Ordenar por\",\n      \"sort\": {\n        \"name\": \"Alfabéticamente\",\n        \"lastUpdate\": \"Última actualización\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"Consentimiento de Cloudflare WARP\",\n      \"description(rich)\": \"Cloudflare WARP es un proveedor de VPN WireGuard gratuito. Al habilitar esta opción, aceptas los ${tos(Términos de servicio)} y la ${privacy(Política de privacidad)} de Cloudflare WARP.\"\n    },\n    \"newVersion\": {\n      \"title\": \"Actualización disponible\",\n      \"msg\": \"Hay disponible una nueva versión de @:common.appTitle. ¿Quieres actualizar ahora?\",\n      \"currentVersion\": \"Versión actual: \",\n      \"newVersion\": \"Nueva versión: \",\n      \"updateNow\": \"Actualizar ahora\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"Esto reemplazará todas las opciones de configuración con los valores proporcionados. ¿Estás seguro?\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"Eliminar perfil\",\n          \"msg\": \"¿Estás seguro de que quieres eliminar este perfil permanentemente?\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"Mejorando la selección automática\",\n          \"msg\": \"Al compartir las aplicaciones seleccionadas, ayudas a completar la lista de \\\"selección automática\\\"\"\n        },\n        \"import\": {\n          \"msg\": \"Esto reemplazará todas tus selecciones actuales de proxy por aplicación. ¿Estás seguro de que quieres continuar?\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"Eliminar regla\",\n          \"msg\": \"¿Estás seguro de que quieres eliminar la regla \\\"$rulename\\\"?\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"Funciones experimentales en uso\",\n      \"msg\": \"Has habilitado algunas funciones experimentales que podrían afectar la calidad de la conexión y causar errores inesperados. Siempre puedes cambiar o restablecer estas opciones desde la página de configuración.\",\n      \"disable\": \"No volver a mostrar\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"Elige un perfil\",\n      \"msg\": \"Para empezar, añade un perfil de conexión que incluya los detalles de tu conexión VPN.\\n\\n¿Aún no tienes un servidor VPN? No te preocupes, sigue el tutorial a continuación para configurar uno rápidamente y de forma gratuita.\",\n      \"helpBtn\": {\n        \"label\": \"Muéstrame cómo\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"Advertencia de enlace externo\",\n      \"youAreAboutToVisit\": \"Estás a punto de visitar:\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"Este sitio web no está en nuestra lista de confianza. Procede con precaución.\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"Etiqueta completa:\",\n      \"type\": \"Tipo:\",\n      \"testTime\": \"Hora de la prueba:\",\n      \"testDelay\": \"Latencia de la prueba:\",\n      \"isSelected\": \"Seleccionado:\",\n      \"isGroup\": \"Es un grupo\",\n      \"isSecure\": \"Es seguro:\",\n      \"port\": \"Puerto:\",\n      \"host\": \"Host:\",\n      \"ip\": \"IP:\",\n      \"countryCode\": \"Código de país:\",\n      \"region\": \"Región:\",\n      \"city\": \"Ciudad:\",\n      \"asn\": \"ASN:\",\n      \"organization\": \"Organización:\",\n      \"location\": \"Ubicación:\",\n      \"postalCode\": \"Código postal:\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"Preguntar cada vez\",\n      \"alertMessage\": \"¿Ocultar o salir de la aplicación?\",\n      \"remember\": \"Recordar mi elección\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"Toca para conectar\",\n    \"connect\": \"Conectar\",\n    \"connecting\": \"Conectando...\",\n    \"connected\": \"Conectado\",\n    \"disconnect\": \"Desconectar\",\n    \"disconnecting\": \"Desconectando...\",\n    \"reconnect\": \"Reconectar\",\n    \"reconnectMsg\": \"Reconectando para aplicar los cambios...\",\n    \"secure\": \"Protegido por WARP\"\n  },\n  \"errors\": {\n    \"unexpected\": \"Error inesperado\",\n    \"connection\": {\n      \"unexpected\": \"Error de conexión inesperado\",\n      \"timeout\": \"Tiempo de conexión agotado\",\n      \"badResponse\": \"Respuesta incorrecta\",\n      \"connectionError\": \"Error de conexión\",\n      \"badCertificate\": \"Certificado no válido\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"Error inesperado\",\n      \"notFound\": \"Perfil no encontrado\",\n      \"invalidConfig\": \"Configuraciones no válidas\",\n      \"invalidUrl\": \"URL no válida\",\n      \"canceledByUser\": \"Cancelado por el usuario\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"Fallo inesperado\",\n      \"missingVpnPermission\": \"Falta el permiso de VPN\",\n      \"missingNotificationPermission\": \"Falta el permiso de notificación\",\n      \"core\": \"Error del núcleo\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"El servicio no se está ejecutando\",\n      \"missingPrivilege\": \"Falta privilegio\",\n      \"missingPrivilegeMsg\": \"El modo VPN requiere privilegios de administrador. Reinicia la aplicación como administrador o cambia el modo de servicio.\",\n      \"invalidConfigOptions\": \"Opciones de configuración no válidas\",\n      \"invalidConfig\": \"Configuración no válida\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"Falta la licencia de WARP\",\n      \"missingLicenseMsg\": \"El perfil seleccionado utiliza la función WARP. Para usar esta función, debes aceptar la licencia de WARP.\"\n    }\n  }\n}"
  },
  {
    "path": "assets/translations/fa.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"هیدیفای\",\n    \"start\": \"شروع\",\n    \"version\": \"نسخه\",\n    \"ok\": \"باشه\",\n    \"cancel\": \"لغو\",\n    \"kContinue\": \"ادامه\",\n    \"showMore\": \"نمایش بیشتر\",\n    \"showLess\": \"نمایش کمتر\",\n    \"filter\": \"فیلتر\",\n    \"all\": \"همه\",\n    \"pause\": \"مکث\",\n    \"resume\": \"ادامه\",\n    \"clear\": \"پاک‌سازی\",\n    \"close\": \"بستن\",\n    \"auto\": \"خودکار\",\n    \"manually\": \"دستی\",\n    \"name\": \"نام\",\n    \"url\": \"URL\",\n    \"add\": \"افزودن\",\n    \"clipboard\": \"کلیپ‌بورد\",\n    \"addToClipboard\": \"افزودن به کلیپ‌بورد\",\n    \"scanQr\": \"اسکن QR\",\n    \"free\": \"رایگان\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Fragment\",\n    \"help\": \"راهنما\",\n    \"save\": \"ذخیره\",\n    \"update\": \"به‌روزرسانی\",\n    \"share\": \"اشتراک‌گذاری\",\n    \"edit\": \"ویرایش\",\n    \"delete\": \"حذف\",\n    \"discard\": \"صرف‌نظر\",\n    \"import\": \"وارد کردن\",\n    \"export\": \"خروجی گرفتن\",\n    \"later\": \"بعداً\",\n    \"ignore\": \"نادیده گرفتن\",\n    \"quit\": \"خروج\",\n    \"notSet\": \"تنظیم نشده\",\n    \"hide\": \"پنهان کردن\",\n    \"exit\": \"خروج\",\n    \"reset\": \"بازنشانی\",\n    \"done\": \"انجام شد\",\n    \"search\": \"جستجو\",\n    \"decline\": \"رد کردن\",\n    \"agree\": \"موافقم\",\n    \"empty\": \"خالی\",\n    \"unknown\": \"ناشناخته\",\n    \"hidden\": \"پنهان\",\n    \"timeout\": \"عدم پاسخ\",\n    \"sort\": \"مرتب‌سازی\",\n    \"dashboard\": \"داشبورد\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"$n روز\",\n        \"other\": \"$n روز\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"$n ساعت\",\n        \"other\": \"$n ساعت\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"دسترسی رد شد\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"با موفقیت در کلیپ‌بورد کپی شد\",\n          \"failure\": \"کپی در کلیپ‌بورد ناموفق بود\",\n          \"contentTooLarge\": \"محتوا بیش از حد بزرگ است. به جای آن از خروجی فایل استفاده کنید\"\n        },\n        \"file\": {\n          \"success\": \"فایل JSON با موفقیت ایجاد شد\",\n          \"failure\": \"ایجاد فایل ناموفق بود\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"تأیید ورود اطلاعات\",\n        \"success\": \"با موفقیت وارد شد\",\n        \"failure\": \"وارد کردن ناموفق بود\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"هرآنچه برای اینترنت بدون محدودیت نیاز دارید\",\n    \"termsAndPolicyCaution(rich)\": \"با ادامه، شما با ${tap(@:pages.about.termsAndConditions)} موافقت می‌کنید\",\n    \"info(rich)\": \"ساخته شده با ❤️ توسط هیدیفای - ${tap_source(متن‌باز)} (${tap_license(مجوز)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"خانه\",\n      \"quickSettings\": \"تنظیمات سریع\"\n    },\n    \"proxies\": {\n      \"title\": \"پروکسی‌ها\",\n      \"sort\": \"مرتب‌سازی پروکسی‌ها\",\n      \"testDelay\": \"تست تأخیر\",\n      \"empty\": \"هیچ پروکسی موجود نیست\",\n      \"activeProxy\": \"پروکسی فعال\",\n      \"unknownIp\": \"IP ناشناخته\",\n      \"sortOptions\": {\n        \"unsorted\": \"پیش‌فرض\",\n        \"name\": \"بر اساس نام\",\n        \"delay\": \"بر اساس تأخیر\"\n      },\n      \"ipInfo\": {\n        \"address\": \"آدرس IP\",\n        \"country\": \"کشور\",\n        \"organization\": \"سازمان\"\n      },\n      \"delay\": {\n        \"result\": \"تأخیر: ${delay} میلی‌ثانیه\",\n        \"timeout\": \"تست تأخیر ناموفق بود\",\n        \"testing\": \"تأخیر: در حال تست...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"پروفایل‌ها\",\n      \"add\": \"افزودن پروفایل\",\n      \"update\": \"به‌روزرسانی پروفایل\",\n      \"viewAllProfiles\": \"مشاهده همه پروفایل‌ها\",\n      \"activeProfileName\": \"نام پروفایل فعال: «${name}»\",\n      \"nonActiveProfileName\": \"انتخاب «${name}» به عنوان پروفایل فعال\",\n      \"freeSubNotFound\": \"اشتراک رایگان یافت نشد\",\n      \"freeSubNotFoundForRegion\": \"اشتراک رایگان برای منطقه «${region}» یافت نشد\",\n      \"failedToLoad\": \"بارگذاری ناموفق بود\",\n      \"updateSubscriptions\": \"به‌روزرسانی اشتراک‌ها\",\n      \"share\": {\n        \"urlToClipboard\": \"URL به کلیپ‌بورد\",\n        \"showUrlQr\": \"نمایش QR کد URL\",\n        \"jsonToClipboard\": \"JSON به کلیپ‌بورد\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"پروفایل با موفقیت ذخیره شد\"\n        },\n        \"invalidUrl\": \"URL نامعتبر است\",\n        \"add\": {\n          \"failure\": \"افزودن پروفایل ناموفق بود\"\n        },\n        \"update\": {\n          \"success\": \"پروفایل با موفقیت به‌روز شد\",\n          \"successNamed\": \"«${name}» با موفقیت به‌روز شد\",\n          \"failure\": \"به‌روزرسانی پروفایل ناموفق بود\",\n          \"failureNamed\": \"به‌روزرسانی «${name}» ناموفق بود\"\n        },\n        \"delete\": {\n          \"success\": \"پروفایل با موفقیت حذف شد\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"پروفایل\",\n      \"lastUpdate\": \"آخرین به‌روزرسانی\",\n      \"form\": {\n        \"nameHint\": \"نام پروفایل\",\n        \"emptyName\": \"نام الزامی است\",\n        \"invalidUrl\": \"URL نامعتبر است\",\n        \"urlHint\": \"URL کامل کانفیگ\",\n        \"disableAutoUpdate\": \"غیرفعال کردن به‌روزرسانی خودکار\",\n        \"autoUpdateInterval\": \"فاصله زمانی به‌روزرسانی خودکار\",\n        \"loading\": \"در حال افزودن پروفایل...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"گزارش‌ها\",\n      \"shareCoreLogs\": \"اشتراک‌گذاری گزارش‌های هسته\",\n      \"shareAppLogs\": \"اشتراک‌گذاری گزارش‌های برنامه\"\n    },\n    \"about\": {\n      \"title\": \"درباره\",\n      \"notAvailableMsg\": \"شما در حال استفاده از آخرین نسخه هستید\",\n      \"checkForUpdate\": \"بررسی برای به‌روزرسانی\",\n      \"openWorkingDir\": \"باز کردن پوشه کاری\",\n      \"sourceCode\": \"کد منبع\",\n      \"telegramChannel\": \"کانال تلگرام\",\n      \"termsAndConditions\": \"شرایط و ضوابط\",\n      \"privacyPolicy\": \"سیاست حفظ حریم خصوصی\"\n    },\n    \"settings\": {\n      \"title\": \"تنظیمات\",\n      \"resetTunnel\": \"بازنشانی پروفایل VPN\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"وارد کردن تنظیمات از کلیپ‌بورد\",\n          \"file\": \"وارد کردن تنظیمات از فایل\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"کپی تنظیمات ناشناس به کلیپ‌بورد\",\n          \"anonymousToFile\": \"خروجی تنظیمات ناشناس به فایل\",\n          \"allToClipboard\": \"کپی تمام تنظیمات به کلیپ‌بورد\",\n          \"allToFile\": \"خروجی تمام تنظیمات به فایل\"\n        },\n        \"reset\": \"بازنشانی تنظیمات\"\n      },\n      \"general\": {\n        \"title\": \"عمومی\",\n        \"locale\": \"زبان\",\n        \"themeMode\": \"حالت پوسته\",\n        \"themeModes\": {\n          \"system\": \"پیش‌فرض سیستم\",\n          \"dark\": \"حالت تیره\",\n          \"light\": \"حالت روشن\",\n          \"black\": \"حالت مشکی\"\n        },\n        \"enableAnalytics\": \"فعال‌سازی آمار\",\n        \"enableAnalyticsMsg\": \"اجازه جمع‌آوری آمار و ارسال گزارش‌های خطا برای بهبود برنامه\",\n        \"autoIpCheck\": \"بررسی خودکار IP اتصال\",\n        \"dynamicNotification\": \"نمایش سرعت در اعلان\",\n        \"hapticFeedback\": \"بازخورد لرزشی\",\n        \"actionAtClosing\": \"اقدام هنگام بستن\",\n        \"autoStart\": \"شروع هنگام ورود به سیستم\",\n        \"silentStart\": \"شروع در حالت کمینه\",\n        \"ignoreBatteryOptimizations\": \"غیرفعال کردن بهینه‌سازی باتری\",\n        \"ignoreBatteryOptimizationsMsg\": \"حذف محدودیت‌ها برای عملکرد بهینه VPN\",\n        \"memoryLimit\": \"محدودیت حافظه\",\n        \"memoryLimitMsg\": \"در صورت مواجهه با خطای کمبود حافظه یا بسته‌شدن‌های مکرر برنامه، این گزینه را فعال کنید\",\n        \"debugMode\": \"حالت اشکال‌زدایی\",\n        \"debugModeMsg\": \"برای اعمال این تغییر، برنامه را مجدداً راه‌اندازی کنید\",\n        \"logLevel\": \"سطح گزارش‌گیری\",\n        \"connectionTestUrl\": \"URL تست اتصال\",\n        \"urlTestInterval\": \"فاصله زمانی تست URL\",\n        \"clashApiPort\": \"پورت Clash API\",\n        \"useXrayCoreWhenPossible\": \"استفاده از xray-core در صورت امکان\",\n        \"useXrayCoreWhenPossibleMsg\": \"هنگام پردازش لینک‌های اشتراک از xray-core استفاده شود. برای فعال‌سازی این گزینه باید لینک اشتراک را مجدداً وارد کنید.\"\n      },\n      \"routing\": {\n        \"title\": \"مسیریابی\",\n        \"perAppProxy\": {\n          \"title\": \"پروکسی برای هر برنامه\",\n          \"hideSysApps\": \"پنهان کردن برنامه‌های سیستمی\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"وارد کردن انتخاب‌ها از کلیپ‌بورد\",\n              \"file\": \"وارد کردن انتخاب‌ها از فایل\",\n              \"msg\": \"وارد کردن، انتخاب‌های فعلی شما را جایگزین خواهد کرد. آیا مطمئن هستید که می‌خواهید ادامه دهید؟\"\n            },\n            \"export\": {\n              \"clipboard\": \"کپی انتخاب‌ها به کلیپ‌بورد\",\n              \"file\": \"خروجی انتخاب‌ها به فایل\"\n            },\n            \"shareToAll\": \"اشتراک‌گذاری با همه\",\n            \"clearAllSelections\": \"پاک کردن تمام انتخاب‌ها\"\n          },\n          \"modes\": {\n            \"all\": \"همه\",\n            \"proxy\": \"پروکسی\",\n            \"bypass\": \"دور زدن\",\n            \"allMsg\": \"پروکسی کردن تمام برنامه‌ها\",\n            \"proxyMsg\": \"فقط برنامه‌های انتخاب‌شده پروکسی شوند\",\n            \"bypassMsg\": \"برنامه‌های انتخاب‌شده پروکسی نشوند\"\n          },\n          \"autoSelection\": {\n            \"title\": \"انتخاب خودکار\",\n            \"performNow\": \"اکنون انجام بده\",\n            \"resetToDefault\": \"بازنشانی به پیش‌فرض\",\n            \"autoUpdateInterval\": \"فاصله زمانی به‌روزرسانی خودکار\",\n            \"toast\": {\n              \"success\": \"انتخاب خودکار برنامه‌ها با موفقیت انجام شد\",\n              \"failure\": \"انتخاب خودکار ناموفق بود\",\n              \"regionNotFound\": \"انتخاب خودکار برای منطقه «${region}» یافت نشد\",\n              \"alreadyInAuto\": \"انتخاب‌های شما از قبل در لیست خودکار موجود است\"\n            },\n            \"dialog\": {\n              \"title\": \"انتخاب خودکار برنامه‌ها\",\n              \"msg\": \"قابلیت انتخاب خودکار برای پروکسی هر برنامه به دلیل تغییر منطقه به «${region}» غیرفعال شد\"\n            }\n          }\n        },\n        \"region\": \"منطقه\",\n        \"regions\": {\n          \"ir\": \"ایران (ir)\",\n          \"cn\": \"چین (cn)\",\n          \"ru\": \"روسیه (ru)\",\n          \"af\": \"افغانستان (af)\",\n          \"id\": \"اندونزی (id)\",\n          \"tr\": \"ترکیه (tr)\",\n          \"br\": \"برزیل (br)\",\n          \"other\": \"سایر\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"استراتژی Balancer\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"مسدودسازی تبلیغات\",\n        \"bypassLan\": \"دور زدن LAN\",\n        \"resolveDestination\": \"تحلیل آدرس مقصد\",\n        \"ipv6Route\": \"مسیریابی IPv6\",\n        \"ipv6Modes\": {\n          \"disable\": \"غیرفعال\",\n          \"enable\": \"فعال\",\n          \"prefer\": \"ترجیحی\",\n          \"only\": \"انحصاری\"\n        },\n        \"routeRule\": {\n          \"title\": \"قوانین مسیریابی\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"وارد کردن قوانین از کلیپ‌بورد\",\n              \"file\": \"وارد کردن قوانین از فایل\"\n            },\n            \"export\": {\n              \"clipboard\": \"کپی قوانین در کلیپ‌بورد\",\n              \"file\": \"ذخیره قوانین در فایل\"\n            },\n            \"reset\": \"بازنشانی قوانین\"\n          },\n          \"deleteRule\": \"حذف قانون\",\n          \"createRule\": \"ایجاد قانون جدید\",\n          \"rule\": {\n            \"title\": \"قانون\",\n            \"ruleChanged\": \"قانون تغییر کرد\",\n            \"ruleChangedMsg\": \"آیا می‌خواهید ویرایش‌های خود را ذخیره کنید؟\",\n            \"onlyTunMode\": \"فقط در حالت TUN در دسترس است\",\n            \"notAvailabeInThisPlatform\": \"در این پلتفرم در دسترس نیست\",\n            \"canNotBeEmpty\": \"نمی‌تواند خالی باشد\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"«URL» معتبر مانند\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe یا google chrome یا chrome\",\n            \"validProcessName\": \"«نام فرآیند» معتبر مانند\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"«مسیر فرآیند» معتبر مانند\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 یا 1-65000\",\n            \"validPortRange\": \"«پورت» یا «محدوده پورت» معتبر مانند\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 یا 10.0.0.0/24\",\n            \"validIpCidr\": \"IP CIDR معتبر مانند\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com یا dl.google.com\",\n            \"validDomain\": \"«دامنه» معتبر مانند\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com یا .ir\",\n            \"validDomainSuffix\": \"«پسوند دامنه» معتبر مانند\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"نام\",\n              \"outbound\": \"خروجی در صورت تطابق\",\n              \"rule_set\": \"URL مجموعه قوانین\",\n              \"package_name\": \"نام‌های بسته\",\n              \"process_name\": \"نام‌های فرآیند\",\n              \"process_path\": \"مسیرهای فرآیند\",\n              \"network\": \"شبکه‌ها\",\n              \"port_range\": \"پورت‌های مقصد\",\n              \"source_port_range\": \"پورت‌های مبدأ\",\n              \"protocol\": \"پروتکل\",\n              \"ip_cidr\": \"IP CIDR مقصد\",\n              \"source_ip_cidr\": \"IP CIDR مبدأ\",\n              \"domain\": \"دامنه\",\n              \"domain_suffixe\": \"پسوند دامنه\",\n              \"domain_keyword\": \"کلمه کلیدی دامنه\",\n              \"domain_regex\": \"عبارت منظم دامنه\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"پروکسی\",\n              \"direct\": \"مستقیم\",\n              \"direct_with_fragment\": \"مستقیم با فرگمنت\",\n              \"block\": \"مسدود\"\n            },\n            \"network(map)\": {\n              \"all\": \"همه\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"همه\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"افزودن مقدار جدید\",\n            \"update\": \"به‌روزرسانی مقدار\",\n            \"clearList\": \"پاک کردن لیست\",\n            \"clearListMsg\": \"تمام موارد حذف شدند\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"برنامه‌های اندروید\",\n            \"showSystemApps\": \"نمایش برنامه‌های سیستمی\",\n            \"hideSystemApps\": \"پنهان کردن برنامه‌های سیستمی\",\n            \"clearSelection\": \"پاک کردن انتخاب‌ها\",\n            \"uninstalled\": \"نصب نشده\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"DNS اصلی (ریموت)\",\n        \"remoteDnsDomainStrategy\": \"استراتژی دامنه DNS\",\n        \"directDns\": \"DNS پروکسی‌ها (مستقیم)\",\n        \"directDnsDomainStrategy\": \"استراتژی دامنه DNS مستقیم\",\n        \"enableDnsRouting\": \"فعال‌سازی مسیریابی DNS\",\n        \"enableFakeDns\": \"فعال‌سازی DNS جعلی\",\n        \"domainStrategy\": {\n          \"auto\": \"خودکار\",\n          \"preferIpv6\": \"ترجیح IPv6\",\n          \"preferIpv4\": \"ترجیح IPv4\",\n          \"ipv4Only\": \"فقط IPv4\",\n          \"ipv6Only\": \"فقط IPv6\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"ورودی\",\n        \"serviceMode\": \"حالت سرویس\",\n        \"serviceModes\": {\n          \"proxy\": \"فقط سرویس پروکسی\",\n          \"systemProxy\": \"تنظیم پروکسی سیستم\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"سرویس VPN\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"پروکسی\",\n          \"systemProxy\": \"پروکسی سیستم\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"سرویس VPN\"\n        },\n        \"strictRoute\": \"مسیربندی سخت‌گیرانه\",\n        \"tunImplementation\": \"پیاده‌سازی Tun\",\n        \"tunImplementations\": {\n          \"mixed\": \"ترکیبی\",\n          \"system\": \"سیستم\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"پورت ترکیبی\",\n        \"tproxyPort\": \"پورت پروکسی شفاف\",\n        \"directPort\": \"پورت مستقیم\",\n        \"redirectPort\": \"پورت تغییر مسیر\",\n        \"allowConnectionFromLan\": \"اشتراک VPN در شبکه محلی\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"ترفندهای TLS\",\n        \"enable\": \"فعال‌سازی fragment\",\n        \"packets\": \"بسته‌های Fragment\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"اندازه fragment\",\n        \"sleep\": \"تأخیر fragment\",\n        \"mixedSniCase\": {\n          \"enable\": \"فعال‌سازی mixed SNI case\"\n        },\n        \"padding\": {\n          \"enable\": \"فعال‌سازی padding\",\n          \"size\": \"اندازه padding\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"فعال‌سازی WARP\",\n        \"generateConfig\": \"ایجاد کانفیگ WARP\",\n        \"configGenerated\": \"کانفیگ Warp ایجاد شد\",\n        \"missingConfig\": \"کانفیگ WARP موجود نیست\",\n        \"detourMode\": \"حالت مسیریابی WARP\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"عبور پروکسی‌ها از طریق WARP\",\n          \"warpOverProxy\": \"عبور WARP از طریق پروکسی‌ها\",\n          \"proxyOverWarpExplain\": \"رفع انسداد پروکسی‌ها با WARP\",\n          \"warpOverProxyExplain\": \"امنیت بیشتر با WARP\"\n        },\n        \"licenseKey\": \"کلید لایسنس\",\n        \"cleanIp\": \"IP تمیز\",\n        \"port\": \"پورت\",\n        \"noise\": {\n          \"count\": \"تعداد نویز\",\n          \"mode\": \"حالت نویز\",\n          \"size\": \"اندازه نویز\",\n          \"delay\": \"تأخیر نویز\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"اتصال\",\n      \"traffic\": \"ترافیک\",\n      \"trafficLive\": \"ترافیک لحظه‌ای\",\n      \"trafficTotal\": \"ترافیک کل\",\n      \"uplink\": \"ارسال\",\n      \"downlink\": \"دریافت\",\n      \"speed\": \"سرعت\",\n      \"totalTransferred\": \"کل منتقل شده\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"آپلود\",\n      \"download\": \"دانلود\",\n      \"total\": \"کل ترافیک\",\n      \"expireDate\": \"تاریخ انقضا\",\n      \"expired\": \"منقضی شده\",\n      \"noTraffic\": \"حجم تمام شده\",\n      \"remainingTime\": \"زمان باقی‌مانده\",\n      \"remainingDuration\": \"${duration} روز باقی‌مانده\",\n      \"remainingDurationNew\": \"${duration} روز\",\n      \"remainingTrafficSemanticLabel\": \"${consumed} از ${total} ترافیک مصرف شده\",\n      \"remainingTraffic\": \"ترافیک باقی‌مانده\",\n      \"remainingUsage\": \"باقی‌مانده\",\n      \"profileSite\": \"سرویس‌دهنده\",\n      \"profileSupport\": \"پشتیبانی\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"مرتب‌سازی بر اساس\",\n      \"sort\": {\n        \"name\": \"بر اساس نام\",\n        \"lastUpdate\": \"آخرین به‌روزرسانی\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"رضایت‌نامه Cloudflare WARP\",\n      \"description(rich)\": \"Cloudflare WARP یک ارائه‌دهنده رایگان WireGuard VPN است. با فعال کردن این گزینه، شما با ${tos(شرایط خدمات)} و ${privacy(سیاست حفظ حریم خصوصی)} Cloudflare WARP موافقت می‌کنید.\"\n    },\n    \"newVersion\": {\n      \"title\": \"به‌روزرسانی موجود است\",\n      \"msg\": \"نسخه جدیدی از @:common.appTitle در دسترس است. آیا مایل به به‌روزرسانی هستید؟\",\n      \"currentVersion\": \"نسخه فعلی: \",\n      \"newVersion\": \"نسخه جدید: \",\n      \"updateNow\": \"اکنون به‌روزرسانی کن\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"این عمل تمام تنظیمات فعلی شما را بازنویسی خواهد کرد. آیا مطمئن هستید؟\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"حذف پروفایل\",\n          \"msg\": \"آیا از حذف دائمی این پروفایل مطمئن هستید؟\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"بهبود انتخاب خودکار\",\n          \"msg\": \"با اشتراک‌گذاری برنامه‌های انتخاب‌شده، به تکمیل لیست «انتخاب خودکار» کمک می‌کنید\"\n        },\n        \"import\": {\n          \"msg\": \"این عمل تمام انتخاب‌های فعلی شما برای پروکسی برنامه‌ها را جایگزین خواهد کرد. آیا مطمئن هستید؟\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"حذف قانون\",\n          \"msg\": \"آیا از حذف قانون «$rulename» مطمئن هستید؟\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"ویژگی‌های آزمایشی در حال استفاده\",\n      \"msg\": \"شما برخی ویژگی‌های آزمایشی را فعال کرده‌اید که ممکن است بر کیفیت اتصال تأثیر گذاشته و باعث خطاهای غیرمنتظره شوند. همیشه می‌توانید این گزینه‌ها را از صفحه تنظیمات تغییر داده یا بازنشانی کنید.\",\n      \"disable\": \"دیگر نمایش نده\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"یک پروفایل انتخاب کنید\",\n      \"msg\": \"بیایید با افزودن یک پروفایل اتصال که شامل جزئیات اتصال VPN شماست، شروع کنیم.\\n\\nهنوز سرور VPN ندارید؟ نگران نباشید، با دنبال کردن راهنمای زیر می‌توانید به سرعت و رایگان یکی برای خودتان بسازید.\",\n      \"helpBtn\": {\n        \"label\": \"راهنمایی کن\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"هشدار لینک خارجی\",\n      \"youAreAboutToVisit\": \"شما در حال بازدید از این آدرس هستید:\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"این وب‌سایت در لیست مورد اعتماد ما نیست. لطفاً با احتیاط ادامه دهید.\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"تگ کامل:\",\n      \"type\": \"نوع:\",\n      \"testTime\": \"زمان تست:\",\n      \"testDelay\": \"تأخیر تست:\",\n      \"isSelected\": \"انتخاب شده:\",\n      \"isGroup\": \"گروه است\",\n      \"isSecure\": \"امن است:\",\n      \"port\": \"پورت:\",\n      \"host\": \"میزبان:\",\n      \"ip\": \"IP:\",\n      \"countryCode\": \"کد کشور:\",\n      \"region\": \"منطقه:\",\n      \"city\": \"شهر:\",\n      \"asn\": \"ASN:\",\n      \"organization\": \"سازمان:\",\n      \"location\": \"مکان:\",\n      \"postalCode\": \"کد پستی:\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"هر بار بپرس\",\n      \"alertMessage\": \"پنهان کردن یا خروج از برنامه؟\",\n      \"remember\": \"انتخابم را به خاطر بسپار\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"برای اتصال ضربه بزنید\",\n    \"connect\": \"اتصال\",\n    \"connecting\": \"در حال اتصال...\",\n    \"connected\": \"متصل شد\",\n    \"disconnect\": \"قطع اتصال\",\n    \"disconnecting\": \"در حال قطع اتصال...\",\n    \"reconnect\": \"اتصال مجدد\",\n    \"reconnectMsg\": \"در حال اتصال مجدد برای اعمال تغییرات...\",\n    \"secure\": \"ایمن شده با WARP\"\n  },\n  \"errors\": {\n    \"unexpected\": \"خطای غیرمنتظره\",\n    \"connection\": {\n      \"unexpected\": \"خطای غیرمنتظره در اتصال\",\n      \"timeout\": \"اتصال با وقفه زمانی مواجه شد\",\n      \"badResponse\": \"پاسخ نامعتبر\",\n      \"connectionError\": \"خطای اتصال\",\n      \"badCertificate\": \"گواهی‌نامه نامعتبر\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"خطای غیرمنتظره\",\n      \"notFound\": \"پروفایل یافت نشد\",\n      \"invalidConfig\": \"کانفیگ‌های نامعتبر\",\n      \"invalidUrl\": \"URL نامعتبر\",\n      \"canceledByUser\": \"توسط کاربر لغو شد\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"شکست غیرمنتظره\",\n      \"missingVpnPermission\": \"مجوز VPN وجود ندارد\",\n      \"missingNotificationPermission\": \"مجوز اعلان وجود ندارد\",\n      \"core\": \"خطای هسته\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"سرویس در حال اجرا نیست\",\n      \"missingPrivilege\": \"دسترسی وجود ندارد\",\n      \"missingPrivilegeMsg\": \"حالت VPN به دسترسی ادمین نیاز دارد. یا برنامه را به عنوان ادمین مجدداً راه‌اندازی کنید یا حالت سرویس را تغییر دهید.\",\n      \"invalidConfigOptions\": \"گزینه‌های پیکربندی نامعتبر\",\n      \"invalidConfig\": \"پیکربندی نامعتبر\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"لایسنس Warp\",\n      \"missingLicenseMsg\": \"پروفایل انتخاب‌شده از ویژگی WARP استفاده می‌کند؛ برای استفاده از این قابلیت، باید با لایسنس WARP موافقت شود.\"\n    }\n  }\n}"
  },
  {
    "path": "assets/translations/fr.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"Hiddify\",\n    \"start\": \"Commencer\",\n    \"version\": \"Version\",\n    \"ok\": \"OK\",\n    \"cancel\": \"Annuler\",\n    \"kContinue\": \"Continuer\",\n    \"showMore\": \"Afficher plus\",\n    \"showLess\": \"Afficher moins\",\n    \"filter\": \"Filtrer\",\n    \"all\": \"Tous\",\n    \"pause\": \"Pause\",\n    \"resume\": \"Reprendre\",\n    \"clear\": \"Effacer\",\n    \"close\": \"Fermer\",\n    \"auto\": \"Automatique\",\n    \"manually\": \"Manuellement\",\n    \"name\": \"Nom\",\n    \"url\": \"URL\",\n    \"add\": \"Ajouter\",\n    \"clipboard\": \"Presse-papiers\",\n    \"addToClipboard\": \"Ajouter au presse-papiers\",\n    \"scanQr\": \"Scanner le QR code\",\n    \"free\": \"Gratuit\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Fragment\",\n    \"help\": \"Aide\",\n    \"save\": \"Enregistrer\",\n    \"update\": \"Mettre à jour\",\n    \"share\": \"Partager\",\n    \"edit\": \"Modifier\",\n    \"delete\": \"Supprimer\",\n    \"discard\": \"Ignorer\",\n    \"import\": \"Importer\",\n    \"export\": \"Exporter\",\n    \"later\": \"Plus tard\",\n    \"ignore\": \"Ignorer\",\n    \"quit\": \"Quitter\",\n    \"notSet\": \"Non défini\",\n    \"hide\": \"Masquer\",\n    \"exit\": \"Quitter\",\n    \"reset\": \"Réinitialiser\",\n    \"done\": \"Terminé\",\n    \"search\": \"Rechercher\",\n    \"decline\": \"Refuser\",\n    \"agree\": \"Accepter\",\n    \"empty\": \"Vide\",\n    \"unknown\": \"Inconnu\",\n    \"hidden\": \"Caché\",\n    \"timeout\": \"Délai expiré\",\n    \"sort\": \"Trier\",\n    \"dashboard\": \"Tableau de bord\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"$n jour\",\n        \"other\": \"$n jours\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"$n heure\",\n        \"other\": \"$n heures\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"Permission refusée\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"Ajouté au presse-papiers avec succès\",\n          \"failure\": \"Échec de la copie dans le presse-papiers\",\n          \"contentTooLarge\": \"Contenu trop volumineux. Utilisez plutôt l'exportation de fichier\"\n        },\n        \"file\": {\n          \"success\": \"Fichier JSON créé avec succès\",\n          \"failure\": \"Échec de la création du fichier\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"Confirmer l'importation\",\n        \"success\": \"Importé avec succès\",\n        \"failure\": \"Échec de l'importation\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"Tout ce dont vous avez besoin pour un internet sans restrictions\",\n    \"termsAndPolicyCaution(rich)\": \"En continuant, vous acceptez les ${tap(@:pages.about.termsAndConditions)}\",\n    \"info(rich)\": \"Fait avec ❤️ par Hiddify - ${tap_source(Open Source)} (${tap_license(Licence)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"Accueil\",\n      \"quickSettings\": \"Réglages rapides\"\n    },\n    \"proxies\": {\n      \"title\": \"Proxys\",\n      \"sort\": \"Trier les proxys\",\n      \"testDelay\": \"Tester le délai\",\n      \"empty\": \"Aucun proxy disponible\",\n      \"activeProxy\": \"Proxy actif\",\n      \"unknownIp\": \"IP inconnue\",\n      \"sortOptions\": {\n        \"unsorted\": \"Par défaut\",\n        \"name\": \"Alphabétiquement\",\n        \"delay\": \"Par latence\"\n      },\n      \"ipInfo\": {\n        \"address\": \"Adresse IP\",\n        \"country\": \"Pays\",\n        \"organization\": \"Organisation\"\n      },\n      \"delay\": {\n        \"result\": \"Latence : ${delay} ms\",\n        \"timeout\": \"Délai du test de latence expiré\",\n        \"testing\": \"Latence : test en cours...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"Profils\",\n      \"add\": \"Ajouter un profil\",\n      \"update\": \"Mettre à jour le profil\",\n      \"viewAllProfiles\": \"Voir tous les profils\",\n      \"activeProfileName\": \"Nom du profil actif : \\\"${name}\\\".\",\n      \"nonActiveProfileName\": \"Sélectionner \\\"${name}\\\" comme profil actif\",\n      \"freeSubNotFound\": \"Aucun abonnement gratuit trouvé\",\n      \"freeSubNotFoundForRegion\": \"Aucun abonnement gratuit trouvé pour la région \\\"${region}\\\"\",\n      \"failedToLoad\": \"Échec du chargement\",\n      \"updateSubscriptions\": \"Mettre à jour les abonnements\",\n      \"share\": {\n        \"urlToClipboard\": \"URL dans le presse-papiers\",\n        \"showUrlQr\": \"Afficher le QR code de l'URL\",\n        \"jsonToClipboard\": \"JSON dans le presse-papiers\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"Profil enregistré avec succès\"\n        },\n        \"invalidUrl\": \"URL invalide\",\n        \"add\": {\n          \"failure\": \"Échec de l'ajout du profil\"\n        },\n        \"update\": {\n          \"success\": \"Profil mis à jour avec succès\",\n          \"successNamed\": \"\\\"${name}\\\" a été mis à jour avec succès\",\n          \"failure\": \"Échec de la mise à jour du profil\",\n          \"failureNamed\": \"Échec de la mise à jour de \\\"${name}\\\"\"\n        },\n        \"delete\": {\n          \"success\": \"Profil supprimé avec succès\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"Profil\",\n      \"lastUpdate\": \"Dernière mise à jour\",\n      \"form\": {\n        \"nameHint\": \"Nom du profil\",\n        \"emptyName\": \"Le nom est requis\",\n        \"invalidUrl\": \"URL invalide\",\n        \"urlHint\": \"URL complète de la configuration\",\n        \"disableAutoUpdate\": \"Désactiver la mise à jour automatique\",\n        \"autoUpdateInterval\": \"Intervalle de mise à jour automatique\",\n        \"loading\": \"Ajout du profil...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"Journaux\",\n      \"shareCoreLogs\": \"Partager les journaux du noyau\",\n      \"shareAppLogs\": \"Partager les journaux de l'application\"\n    },\n    \"about\": {\n      \"title\": \"À propos\",\n      \"notAvailableMsg\": \"Vous utilisez déjà la dernière version\",\n      \"checkForUpdate\": \"Vérifier les mises à jour\",\n      \"openWorkingDir\": \"Ouvrir le répertoire de travail\",\n      \"sourceCode\": \"Code source\",\n      \"telegramChannel\": \"Canal Telegram\",\n      \"termsAndConditions\": \"Conditions d'utilisation\",\n      \"privacyPolicy\": \"Politique de confidentialité\"\n    },\n    \"settings\": {\n      \"title\": \"Paramètres\",\n      \"resetTunnel\": \"Réinitialiser le profil VPN\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"Importer les options depuis le presse-papiers\",\n          \"file\": \"Importer les options depuis un fichier\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"Copier les options anonymes dans le presse-papiers\",\n          \"anonymousToFile\": \"Exporter les options anonymes vers un fichier\",\n          \"allToClipboard\": \"Copier toutes les options dans le presse-papiers\",\n          \"allToFile\": \"Exporter toutes les options vers un fichier\"\n        },\n        \"reset\": \"Réinitialiser les options\"\n      },\n      \"general\": {\n        \"title\": \"Général\",\n        \"locale\": \"Langue\",\n        \"themeMode\": \"Thème\",\n        \"themeModes\": {\n          \"system\": \"Thème du système par défaut\",\n          \"dark\": \"Mode sombre\",\n          \"light\": \"Mode clair\",\n          \"black\": \"Mode noir\"\n        },\n        \"enableAnalytics\": \"Activer les statistiques\",\n        \"enableAnalyticsMsg\": \"Autoriser la collecte de statistiques et de rapports d'erreurs pour améliorer l'application\",\n        \"autoIpCheck\": \"Vérifier automatiquement l'IP de connexion\",\n        \"dynamicNotification\": \"Afficher la vitesse dans la notification\",\n        \"hapticFeedback\": \"Retour haptique\",\n        \"actionAtClosing\": \"Action à la fermeture\",\n        \"autoStart\": \"Lancer au démarrage\",\n        \"silentStart\": \"Démarrer réduit\",\n        \"ignoreBatteryOptimizations\": \"Désactiver l'optimisation de la batterie\",\n        \"ignoreBatteryOptimizationsMsg\": \"Supprimer les restrictions pour une performance VPN optimale\",\n        \"memoryLimit\": \"Limite de mémoire\",\n        \"memoryLimitMsg\": \"Activer si vous rencontrez des erreurs de mémoire insuffisante ou des plantages fréquents de l'application\",\n        \"debugMode\": \"Mode de débogage\",\n        \"debugModeMsg\": \"Redémarrez l'application pour appliquer cette modification\",\n        \"logLevel\": \"Niveau de journalisation\",\n        \"connectionTestUrl\": \"URL de test de connexion\",\n        \"urlTestInterval\": \"Intervalle de test de l'URL\",\n        \"clashApiPort\": \"Port de l'API Clash\",\n        \"useXrayCoreWhenPossible\": \"Utiliser xray-core si possible\",\n        \"useXrayCoreWhenPossibleMsg\": \"Utilisez xray-core lors de l'analyse des liens d'abonnement. Vous devez réimporter le lien pour activer cette option\"\n      },\n      \"routing\": {\n        \"title\": \"Routage\",\n        \"perAppProxy\": {\n          \"title\": \"Proxy par application\",\n          \"hideSysApps\": \"Masquer les applications système\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Importer la sélection depuis le presse-papiers\",\n              \"file\": \"Importer la sélection depuis un fichier\",\n              \"msg\": \"L'importation remplacera vos sélections actuelles. Êtes-vous sûr de vouloir continuer ?\"\n            },\n            \"export\": {\n              \"clipboard\": \"Copier la sélection dans le presse-papiers\",\n              \"file\": \"Exporter la sélection vers un fichier\"\n            },\n            \"shareToAll\": \"Partager avec tous\",\n            \"clearAllSelections\": \"Effacer toutes les sélections\"\n          },\n          \"modes\": {\n            \"all\": \"Toutes\",\n            \"proxy\": \"Proxy\",\n            \"bypass\": \"Contourner\",\n            \"allMsg\": \"Utiliser le proxy pour toutes les applications\",\n            \"proxyMsg\": \"Utiliser le proxy uniquement pour les applications sélectionnées\",\n            \"bypassMsg\": \"Ne pas utiliser le proxy pour les applications sélectionnées\"\n          },\n          \"autoSelection\": {\n            \"title\": \"Sélection automatique\",\n            \"performNow\": \"Exécuter maintenant\",\n            \"resetToDefault\": \"Réinitialiser par défaut\",\n            \"autoUpdateInterval\": \"Intervalle de mise à jour automatique\",\n            \"toast\": {\n              \"success\": \"Sélection automatique des applications terminée avec succès\",\n              \"failure\": \"Échec de la sélection automatique\",\n              \"regionNotFound\": \"Sélection automatique non trouvée pour la région \\\"${region}\\\"\",\n              \"alreadyInAuto\": \"Vos sélections sont déjà dans la liste automatique\"\n            },\n            \"dialog\": {\n              \"title\": \"Sélection automatique des applications\",\n              \"msg\": \"La fonction de sélection automatique pour le proxy par application a été désactivée en raison du changement de région vers \\\"${region}\\\"\"\n            }\n          }\n        },\n        \"region\": \"Région\",\n        \"regions\": {\n          \"ir\": \"Iran (ir)\",\n          \"cn\": \"Chine (cn)\",\n          \"ru\": \"Russie (ru)\",\n          \"af\": \"Afghanistan (af)\",\n          \"id\": \"Indonésie (id)\",\n          \"tr\": \"Turquie (tr)\",\n          \"br\": \"Brésil (br)\",\n          \"other\": \"Autre\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"Stratégie de Balancer\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"Bloquer les publicités\",\n        \"bypassLan\": \"Contourner le LAN\",\n        \"resolveDestination\": \"Résoudre la destination\",\n        \"ipv6Route\": \"Route IPv6\",\n        \"ipv6Modes\": {\n          \"disable\": \"Désactiver\",\n          \"enable\": \"Activer\",\n          \"prefer\": \"Préféré\",\n          \"only\": \"Uniquement\"\n        },\n        \"routeRule\": {\n          \"title\": \"Règles de routage\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Importer les règles depuis le presse-papiers\",\n              \"file\": \"Importer les règles depuis un fichier\"\n            },\n            \"export\": {\n              \"clipboard\": \"Copier les règles dans le presse-papiers\",\n              \"file\": \"Enregistrer les règles dans un fichier\"\n            },\n            \"reset\": \"Réinitialiser les règles\"\n          },\n          \"deleteRule\": \"Supprimer la règle\",\n          \"createRule\": \"Créer une nouvelle règle\",\n          \"rule\": {\n            \"title\": \"Règle\",\n            \"ruleChanged\": \"Règle modifiée\",\n            \"ruleChangedMsg\": \"Voulez-vous enregistrer vos modifications ?\",\n            \"onlyTunMode\": \"Disponible uniquement en mode TUN\",\n            \"notAvailabeInThisPlatform\": \"Non disponible sur cette plateforme\",\n            \"canNotBeEmpty\": \"Ne peut pas être vide\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"\\\"URL\\\" valide comme\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe ou google chrome ou chrome\",\n            \"validProcessName\": \"\\\"Nom de processus\\\" valide comme\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"\\\"Chemin de processus\\\" valide comme\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 ou 1-65000\",\n            \"validPortRange\": \"\\\"Port\\\" ou \\\"Plage de ports\\\" valide comme\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 ou 10.0.0.0/24\",\n            \"validIpCidr\": \"IP CIDR valide comme\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com ou dl.google.com\",\n            \"validDomain\": \"\\\"Domaine\\\" valide comme\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com ou .ir\",\n            \"validDomainSuffix\": \"\\\"Suffixe de domaine\\\" valide comme\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"Nom\",\n              \"outbound\": \"Sortie si correspondance\",\n              \"rule_set\": \"URL de l'ensemble de règles\",\n              \"package_name\": \"Noms de paquets\",\n              \"process_name\": \"Noms de processus\",\n              \"process_path\": \"Chemins de processus\",\n              \"network\": \"Réseaux\",\n              \"port_range\": \"Ports de destination\",\n              \"source_port_range\": \"Ports source\",\n              \"protocol\": \"Protocole\",\n              \"ip_cidr\": \"IP CIDR de destination\",\n              \"source_ip_cidr\": \"IP CIDR source\",\n              \"domain\": \"Domaine\",\n              \"domain_suffixe\": \"Suffixe de domaine\",\n              \"domain_keyword\": \"Mot-clé de domaine\",\n              \"domain_regex\": \"Expression régulière de domaine\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"Proxy\",\n              \"direct\": \"Direct\",\n              \"direct_with_fragment\": \"Direct avec fragment\",\n              \"block\": \"Bloquer\"\n            },\n            \"network(map)\": {\n              \"all\": \"Tous\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"Tous\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"Ajouter une nouvelle valeur\",\n            \"update\": \"Mettre à jour la valeur\",\n            \"clearList\": \"Vider la liste\",\n            \"clearListMsg\": \"Tous les éléments ont été supprimés\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"Applications Android\",\n            \"showSystemApps\": \"Afficher les applications système\",\n            \"hideSystemApps\": \"Masquer les applications système\",\n            \"clearSelection\": \"Effacer la sélection\",\n            \"uninstalled\": \"Désinstallé\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"DNS distant\",\n        \"remoteDnsDomainStrategy\": \"Stratégie de domaine DNS distant\",\n        \"directDns\": \"Résolveur de serveur sortant (direct)\",\n        \"directDnsDomainStrategy\": \"Stratégie de domaine sortant\",\n        \"enableDnsRouting\": \"Activer le routage DNS\",\n        \"enableFakeDns\": \"Activer le faux DNS\",\n        \"domainStrategy\": {\n          \"auto\": \"Auto\",\n          \"preferIpv6\": \"Préférer IPv6\",\n          \"preferIpv4\": \"Préférer IPv4\",\n          \"ipv4Only\": \"IPv4 uniquement\",\n          \"ipv6Only\": \"IPv6 uniquement\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"Entrant\",\n        \"serviceMode\": \"Mode de service\",\n        \"serviceModes\": {\n          \"proxy\": \"Service proxy uniquement\",\n          \"systemProxy\": \"Définir le proxy système\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"Service VPN\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"Proxy\",\n          \"systemProxy\": \"Proxy système\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"Service VPN\"\n        },\n        \"strictRoute\": \"Routage strict\",\n        \"tunImplementation\": \"Implémentation TUN\",\n        \"tunImplementations\": {\n          \"mixed\": \"Mixte\",\n          \"system\": \"Système\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"Port mixte\",\n        \"tproxyPort\": \"Port de proxy transparent\",\n        \"directPort\": \"Port direct local\",\n        \"redirectPort\": \"Port de redirection\",\n        \"allowConnectionFromLan\": \"Partager le VPN sur le réseau local\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"Astuces TLS\",\n        \"enable\": \"Activer le fragment\",\n        \"packets\": \"Paquets de fragmentation\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"Taille du fragment\",\n        \"sleep\": \"Délai du fragment\",\n        \"mixedSniCase\": {\n          \"enable\": \"Activer la casse mixte pour SNI\"\n        },\n        \"padding\": {\n          \"enable\": \"Activer le remplissage\",\n          \"size\": \"Taille du remplissage\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"Activer WARP\",\n        \"generateConfig\": \"Générer la configuration WARP\",\n        \"configGenerated\": \"Configuration WARP générée\",\n        \"missingConfig\": \"Configuration WARP manquante\",\n        \"detourMode\": \"Mode de détour\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"Détourner les proxys via WARP\",\n          \"warpOverProxy\": \"Détourner WARP via les proxys\",\n          \"proxyOverWarpExplain\": \"Débloquer les proxys avec WARP\",\n          \"warpOverProxyExplain\": \"Sécurité supplémentaire avec WARP\"\n        },\n        \"licenseKey\": \"Clé de licence\",\n        \"cleanIp\": \"IP propre\",\n        \"port\": \"Port\",\n        \"noise\": {\n          \"count\": \"Nombre de bruits\",\n          \"mode\": \"Mode bruit\",\n          \"size\": \"Taille du bruit\",\n          \"delay\": \"Délai du bruit\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"Connexion\",\n      \"traffic\": \"Trafic\",\n      \"trafficLive\": \"Trafic en direct\",\n      \"trafficTotal\": \"Trafic total\",\n      \"uplink\": \"Envoi\",\n      \"downlink\": \"Réception\",\n      \"speed\": \"Vitesse\",\n      \"totalTransferred\": \"Total transféré\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"Envoi\",\n      \"download\": \"Téléchargement\",\n      \"total\": \"Trafic total\",\n      \"expireDate\": \"Date d'expiration\",\n      \"expired\": \"Expiré\",\n      \"noTraffic\": \"Quota épuisé\",\n      \"remainingTime\": \"Temps restant\",\n      \"remainingDuration\": \"${duration} jours restants\",\n      \"remainingDurationNew\": \"${duration} jours\",\n      \"remainingTrafficSemanticLabel\": \"${consumed} sur ${total} de trafic consommé\",\n      \"remainingTraffic\": \"Trafic restant\",\n      \"remainingUsage\": \"Restant\",\n      \"profileSite\": \"Fournisseur\",\n      \"profileSupport\": \"Support\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"Trier par\",\n      \"sort\": {\n        \"name\": \"Alphabétiquement\",\n        \"lastUpdate\": \"Dernière mise à jour\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"Consentement Cloudflare WARP\",\n      \"description(rich)\": \"Cloudflare WARP est un fournisseur VPN WireGuard gratuit. En activant cette option, vous acceptez les ${tos(Conditions d'utilisation)} et la ${privacy(Politique de confidentialité)} de Cloudflare WARP.\"\n    },\n    \"newVersion\": {\n      \"title\": \"Mise à jour disponible\",\n      \"msg\": \"Une nouvelle version de @:common.appTitle est disponible. Voulez-vous mettre à jour maintenant ?\",\n      \"currentVersion\": \"Version actuelle : \",\n      \"newVersion\": \"Nouvelle version : \",\n      \"updateNow\": \"Mettre à jour\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"Cette action remplacera toutes les options de configuration par les valeurs fournies. Êtes-vous sûr ?\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"Supprimer le profil\",\n          \"msg\": \"Êtes-vous sûr de vouloir supprimer ce profil définitivement ?\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"Améliorer la sélection automatique\",\n          \"msg\": \"En partageant les applications sélectionnées, vous aidez à compléter la liste de \\\"sélection automatique\\\"\"\n        },\n        \"import\": {\n          \"msg\": \"Cette action remplacera toutes vos sélections actuelles de proxy par application. Êtes-vous sûr de vouloir continuer ?\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"Supprimer la règle\",\n          \"msg\": \"Êtes-vous sûr de vouloir supprimer la règle \\\"$rulename\\\" ?\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"Fonctionnalités expérimentales en cours d'utilisation\",\n      \"msg\": \"Vous avez activé des fonctionnalités expérimentales qui pourraient affecter la qualité de la connexion et causer des erreurs inattendues. Vous pouvez toujours modifier ou réinitialiser ces options depuis la page de configuration.\",\n      \"disable\": \"Ne plus afficher\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"Choisissez un profil\",\n      \"msg\": \"Pour commencer, ajoutez un profil de connexion qui inclut les détails de votre connexion VPN.\\n\\nVous n'avez pas encore de serveur VPN ? Pas de problème, suivez le tutoriel ci-dessous pour en configurer un rapidement et gratuitement.\",\n      \"helpBtn\": {\n        \"label\": \"Montrez-moi comment\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"Avertissement de lien externe\",\n      \"youAreAboutToVisit\": \"Vous êtes sur le point de visiter :\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"Ce site web ne figure pas dans notre liste de confiance. Veuillez procéder avec prudence.\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"Tag complet :\",\n      \"type\": \"Type :\",\n      \"testTime\": \"Heure du test :\",\n      \"testDelay\": \"Délai du test :\",\n      \"isSelected\": \"Sélectionné :\",\n      \"isGroup\": \"Est un groupe\",\n      \"isSecure\": \"Est sécurisé :\",\n      \"port\": \"Port :\",\n      \"host\": \"Hôte :\",\n      \"ip\": \"IP :\",\n      \"countryCode\": \"Code pays :\",\n      \"region\": \"Région :\",\n      \"city\": \"Ville :\",\n      \"asn\": \"ASN :\",\n      \"organization\": \"Organisation :\",\n      \"location\": \"Emplacement :\",\n      \"postalCode\": \"Code postal :\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"Demander à chaque fois\",\n      \"alertMessage\": \"Masquer ou quitter l'application ?\",\n      \"remember\": \"Mémoriser mon choix\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"Appuyez pour vous connecter\",\n    \"connect\": \"Connecter\",\n    \"connecting\": \"Connexion en cours...\",\n    \"connected\": \"Connecté\",\n    \"disconnect\": \"Déconnecter\",\n    \"disconnecting\": \"Déconnexion en cours...\",\n    \"reconnect\": \"Reconnecter\",\n    \"reconnectMsg\": \"Reconnexion pour prendre en compte les changements...\",\n    \"secure\": \"Sécurisé par WARP\"\n  },\n  \"errors\": {\n    \"unexpected\": \"Erreur inattendue\",\n    \"connection\": {\n      \"unexpected\": \"Erreur de connexion inattendue\",\n      \"timeout\": \"Délai de connexion expiré\",\n      \"badResponse\": \"Mauvaise réponse\",\n      \"connectionError\": \"Erreur de connexion\",\n      \"badCertificate\": \"Certificat invalide\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"Erreur inattendue\",\n      \"notFound\": \"Profil non trouvé\",\n      \"invalidConfig\": \"Configurations invalides\",\n      \"invalidUrl\": \"URL invalide\",\n      \"canceledByUser\": \"Annulé par l'utilisateur\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"Échec inattendu\",\n      \"missingVpnPermission\": \"Autorisation VPN manquante\",\n      \"missingNotificationPermission\": \"Autorisation de notification manquante\",\n      \"core\": \"Erreur du noyau\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"Le service n'est pas en cours d'exécution\",\n      \"missingPrivilege\": \"Autorisation manquante\",\n      \"missingPrivilegeMsg\": \"Le mode VPN nécessite des droits d'administrateur. Veuillez relancer l'application en tant qu'administrateur ou changer le mode de service.\",\n      \"invalidConfigOptions\": \"Options de configuration invalides\",\n      \"invalidConfig\": \"Configuration invalide\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"Licence WARP manquante\",\n      \"missingLicenseMsg\": \"Le profil sélectionné utilise la fonctionnalité WARP. Pour utiliser cette fonctionnalité, vous devez accepter la licence WARP.\"\n    }\n  }\n}"
  },
  {
    "path": "assets/translations/id.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"Hiddify\",\n    \"start\": \"Mulai\",\n    \"version\": \"Versi\",\n    \"ok\": \"Oke\",\n    \"cancel\": \"Batal\",\n    \"kContinue\": \"Lanjutkan\",\n    \"showMore\": \"Tampilkan lebih banyak\",\n    \"showLess\": \"Tampilkan lebih sedikit\",\n    \"filter\": \"Filter\",\n    \"all\": \"Semua\",\n    \"pause\": \"Jeda\",\n    \"resume\": \"Lanjutkan\",\n    \"clear\": \"Bersihkan\",\n    \"close\": \"Tutup\",\n    \"auto\": \"Otomatis\",\n    \"manually\": \"Manual\",\n    \"name\": \"Nama\",\n    \"url\": \"URL\",\n    \"add\": \"Tambah\",\n    \"clipboard\": \"Papan klip\",\n    \"addToClipboard\": \"Tambah ke papan klip\",\n    \"scanQr\": \"Pindai QR\",\n    \"free\": \"Gratis\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Fragmen\",\n    \"help\": \"Bantuan\",\n    \"save\": \"Simpan\",\n    \"update\": \"Perbarui\",\n    \"share\": \"Bagikan\",\n    \"edit\": \"Edit\",\n    \"delete\": \"Hapus\",\n    \"discard\": \"Buang\",\n    \"import\": \"Impor\",\n    \"export\": \"Ekspor\",\n    \"later\": \"Nanti\",\n    \"ignore\": \"Abaikan\",\n    \"quit\": \"Keluar\",\n    \"notSet\": \"Belum diatur\",\n    \"hide\": \"Sembunyikan\",\n    \"exit\": \"Keluar\",\n    \"reset\": \"Setel ulang\",\n    \"done\": \"Selesai\",\n    \"search\": \"Cari\",\n    \"decline\": \"Tolak\",\n    \"agree\": \"Setuju\",\n    \"empty\": \"Kosong\",\n    \"unknown\": \"Tidak dikenal\",\n    \"hidden\": \"Tersembunyi\",\n    \"timeout\": \"Waktu habis\",\n    \"sort\": \"Urutkan\",\n    \"dashboard\": \"Dasbor\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"$n hari\",\n        \"other\": \"$n hari\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"$n jam\",\n        \"other\": \"$n jam\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"Izin ditolak\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"Berhasil ditambahkan ke papan klip\",\n          \"failure\": \"Gagal menyalin ke papan klip\",\n          \"contentTooLarge\": \"Konten terlalu besar. Gunakan ekspor file saja\"\n        },\n        \"file\": {\n          \"success\": \"File JSON berhasil dibuat\",\n          \"failure\": \"Gagal membuat file\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"Konfirmasi impor\",\n        \"success\": \"Berhasil diimpor\",\n        \"failure\": \"Gagal mengimpor\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"Semua yang Anda butuhkan untuk internet tanpa batasan\",\n    \"termsAndPolicyCaution(rich)\": \"Dengan melanjutkan, Anda menyetujui ${tap(@:pages.about.termsAndConditions)}\",\n    \"info(rich)\": \"Dibuat dengan ❤️ oleh Hiddify - ${tap_source(Sumber Terbuka)} (${tap_license(Lisensi)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"Beranda\",\n      \"quickSettings\": \"Pengaturan cepat\"\n    },\n    \"proxies\": {\n      \"title\": \"Proxy\",\n      \"sort\": \"Urutkan proksi\",\n      \"testDelay\": \"Uji latensi\",\n      \"empty\": \"Tidak ada proksi yang tersedia\",\n      \"activeProxy\": \"Proksi aktif\",\n      \"unknownIp\": \"IP tidak dikenal\",\n      \"sortOptions\": {\n        \"unsorted\": \"Default\",\n        \"name\": \"Berdasarkan abjad\",\n        \"delay\": \"Berdasarkan latensi\"\n      },\n      \"ipInfo\": {\n        \"address\": \"Alamat IP\",\n        \"country\": \"Negara\",\n        \"organization\": \"Organisasi\"\n      },\n      \"delay\": {\n        \"result\": \"Latensi: ${delay}ms\",\n        \"timeout\": \"Waktu tes latensi habis\",\n        \"testing\": \"Latensi: sedang menguji...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"Profil\",\n      \"add\": \"Tambah profil\",\n      \"update\": \"Perbarui profil\",\n      \"viewAllProfiles\": \"Lihat semua profil\",\n      \"activeProfileName\": \"Nama profil aktif: \\\"${name}\\\".\",\n      \"nonActiveProfileName\": \"Pilih \\\"${name}\\\" sebagai profil aktif\",\n      \"freeSubNotFound\": \"Tidak ada langganan gratis yang ditemukan\",\n      \"freeSubNotFoundForRegion\": \"Tidak ada langganan gratis yang ditemukan untuk wilayah \\\"${region}\\\"\",\n      \"failedToLoad\": \"Gagal memuat\",\n      \"updateSubscriptions\": \"Perbarui langganan\",\n      \"share\": {\n        \"urlToClipboard\": \"URL ke papan klip\",\n        \"showUrlQr\": \"Tampilkan QR URL\",\n        \"jsonToClipboard\": \"JSON ke papan klip\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"Profil berhasil disimpan\"\n        },\n        \"invalidUrl\": \"URL tidak valid\",\n        \"add\": {\n          \"failure\": \"Gagal menambahkan profil\"\n        },\n        \"update\": {\n          \"success\": \"Profil berhasil diperbarui\",\n          \"successNamed\": \"\\\"${name}\\\" berhasil diperbarui\",\n          \"failure\": \"Gagal memperbarui profil\",\n          \"failureNamed\": \"Gagal memperbarui \\\"${name}\\\"\"\n        },\n        \"delete\": {\n          \"success\": \"Profil berhasil dihapus\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"Profil\",\n      \"lastUpdate\": \"Terakhir diperbarui\",\n      \"form\": {\n        \"nameHint\": \"Nama profil\",\n        \"emptyName\": \"Nama wajib diisi\",\n        \"invalidUrl\": \"URL tidak valid\",\n        \"urlHint\": \"URL konfigurasi lengkap\",\n        \"disableAutoUpdate\": \"Nonaktifkan pembaruan otomatis\",\n        \"autoUpdateInterval\": \"Interval pembaruan otomatis\",\n        \"loading\": \"Menambahkan profil...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"Log\",\n      \"shareCoreLogs\": \"Bagikan log inti\",\n      \"shareAppLogs\": \"Bagikan log aplikasi\"\n    },\n    \"about\": {\n      \"title\": \"Tentang\",\n      \"notAvailableMsg\": \"Anda sudah menggunakan versi terbaru\",\n      \"checkForUpdate\": \"Periksa pembaruan\",\n      \"openWorkingDir\": \"Buka direktori kerja\",\n      \"sourceCode\": \"Kode sumber\",\n      \"telegramChannel\": \"Saluran Telegram\",\n      \"termsAndConditions\": \"Syarat dan Ketentuan\",\n      \"privacyPolicy\": \"Kebijakan Privasi\"\n    },\n    \"settings\": {\n      \"title\": \"Pengaturan\",\n      \"resetTunnel\": \"Setel ulang profil VPN\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"Impor opsi dari papan klip\",\n          \"file\": \"Impor opsi dari file\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"Salin opsi anonim ke papan klip\",\n          \"anonymousToFile\": \"Ekspor opsi anonim ke file\",\n          \"allToClipboard\": \"Salin semua opsi ke papan klip\",\n          \"allToFile\": \"Ekspor semua opsi ke file\"\n        },\n        \"reset\": \"Setel ulang opsi\"\n      },\n      \"general\": {\n        \"title\": \"Umum\",\n        \"locale\": \"Bahasa\",\n        \"themeMode\": \"Tema\",\n        \"themeModes\": {\n          \"system\": \"Default sistem\",\n          \"dark\": \"Mode gelap\",\n          \"light\": \"Mode terang\",\n          \"black\": \"Mode hitam\"\n        },\n        \"enableAnalytics\": \"Aktifkan analitik\",\n        \"enableAnalyticsMsg\": \"Berikan izin untuk mengumpulkan analitik dan mengirim laporan kerusakan untuk meningkatkan aplikasi\",\n        \"autoIpCheck\": \"Periksa IP koneksi secara otomatis\",\n        \"dynamicNotification\": \"Tampilkan kecepatan di notifikasi\",\n        \"hapticFeedback\": \"Umpan balik haptik\",\n        \"actionAtClosing\": \"Tindakan saat menutup\",\n        \"autoStart\": \"Mulai saat masuk\",\n        \"silentStart\": \"Mulai diminimalkan\",\n        \"ignoreBatteryOptimizations\": \"Nonaktifkan optimasi baterai\",\n        \"ignoreBatteryOptimizationsMsg\": \"Hapus batasan untuk kinerja VPN yang optimal\",\n        \"memoryLimit\": \"Batas memori\",\n        \"memoryLimitMsg\": \"Aktifkan jika Anda mengalami kesalahan kehabisan memori atau aplikasi sering macet\",\n        \"debugMode\": \"Mode debug\",\n        \"debugModeMsg\": \"Mulai ulang aplikasi untuk menerapkan perubahan ini\",\n        \"logLevel\": \"Level log\",\n        \"connectionTestUrl\": \"URL uji koneksi\",\n        \"urlTestInterval\": \"Interval uji URL\",\n        \"clashApiPort\": \"Port API Clash\",\n        \"useXrayCoreWhenPossible\": \"Gunakan xray-core jika memungkinkan\",\n        \"useXrayCoreWhenPossibleMsg\": \"Gunakan xray-core saat mengurai tautan langganan. Anda perlu mengimpor ulang tautan untuk mengaktifkan opsi ini.\"\n      },\n      \"routing\": {\n        \"title\": \"Perutean\",\n        \"perAppProxy\": {\n          \"title\": \"Proxy per aplikasi\",\n          \"hideSysApps\": \"Sembunyikan aplikasi sistem\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Impor pilihan dari papan klip\",\n              \"file\": \"Impor pilihan dari file\",\n              \"msg\": \"Mengimpor akan menggantikan pilihan Anda saat ini. Anda yakin ingin melanjutkan?\"\n            },\n            \"export\": {\n              \"clipboard\": \"Salin pilihan ke papan klip\",\n              \"file\": \"Ekspor pilihan ke file\"\n            },\n            \"shareToAll\": \"Bagikan ke semua\",\n            \"clearAllSelections\": \"Hapus semua pilihan\"\n          },\n          \"modes\": {\n            \"all\": \"Semua\",\n            \"proxy\": \"Proxy\",\n            \"bypass\": \"Lewati\",\n            \"allMsg\": \"Proxy semua aplikasi\",\n            \"proxyMsg\": \"Proxy hanya aplikasi yang dipilih\",\n            \"bypassMsg\": \"Jangan proxy aplikasi yang dipilih\"\n          },\n          \"autoSelection\": {\n            \"title\": \"Pilihan otomatis\",\n            \"performNow\": \"Lakukan sekarang\",\n            \"resetToDefault\": \"Setel ulang ke default\",\n            \"autoUpdateInterval\": \"Interval pembaruan otomatis\",\n            \"toast\": {\n              \"success\": \"Pilihan aplikasi otomatis berhasil diselesaikan\",\n              \"failure\": \"Pilihan otomatis gagal\",\n              \"regionNotFound\": \"Pilihan otomatis tidak ditemukan untuk wilayah \\\"${region}\\\"\",\n              \"alreadyInAuto\": \"Pilihan Anda sudah ada dalam daftar otomatis\"\n            },\n            \"dialog\": {\n              \"title\": \"Pilihan aplikasi otomatis\",\n              \"msg\": \"Fitur pilihan otomatis untuk proxy per aplikasi dinonaktifkan karena perubahan wilayah menjadi \\\"${region}\\\"\"\n            }\n          }\n        },\n        \"region\": \"Wilayah\",\n        \"regions\": {\n          \"ir\": \"Iran (ir)\",\n          \"cn\": \"Tiongkok (cn)\",\n          \"ru\": \"Rusia (ru)\",\n          \"af\": \"Afghanistan (af)\",\n          \"id\": \"Indonesia (id)\",\n          \"tr\": \"Turki (tr)\",\n          \"br\": \"Brasil (br)\",\n          \"other\": \"Lainnya\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"Strategi Balancer\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"Blokir iklan\",\n        \"bypassLan\": \"Lewati LAN\",\n        \"resolveDestination\": \"Resolusi tujuan\",\n        \"ipv6Route\": \"Rute IPv6\",\n        \"ipv6Modes\": {\n          \"disable\": \"Nonaktifkan\",\n          \"enable\": \"Aktifkan\",\n          \"prefer\": \"Prioritaskan\",\n          \"only\": \"Hanya\"\n        },\n        \"routeRule\": {\n          \"title\": \"Aturan perutean\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Impor aturan dari papan klip\",\n              \"file\": \"Impor aturan dari file\"\n            },\n            \"export\": {\n              \"clipboard\": \"Salin aturan ke papan klip\",\n              \"file\": \"Simpan aturan ke file\"\n            },\n            \"reset\": \"Setel ulang aturan\"\n          },\n          \"deleteRule\": \"Hapus aturan\",\n          \"createRule\": \"Buat aturan baru\",\n          \"rule\": {\n            \"title\": \"Aturan\",\n            \"ruleChanged\": \"Aturan diubah\",\n            \"ruleChangedMsg\": \"Apakah Anda ingin menyimpan editan Anda?\",\n            \"onlyTunMode\": \"Hanya tersedia dalam mode TUN\",\n            \"notAvailabeInThisPlatform\": \"Tidak tersedia di platform ini\",\n            \"canNotBeEmpty\": \"Tidak boleh kosong\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"\\\"URL\\\" yang valid seperti\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe atau google chrome atau chrome\",\n            \"validProcessName\": \"\\\"Nama Proses\\\" yang valid seperti\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"\\\"Jalur Proses\\\" yang valid seperti\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 atau 1-65000\",\n            \"validPortRange\": \"\\\"Port\\\" atau \\\"Rentang Port\\\" yang valid seperti\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 atau 10.0.0.0/24\",\n            \"validIpCidr\": \"IP CIDR yang valid seperti\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com atau dl.google.com\",\n            \"validDomain\": \"\\\"Domain\\\" yang valid seperti\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com atau .ir\",\n            \"validDomainSuffix\": \"\\\"Sufiks Domain\\\" yang valid seperti\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"Nama\",\n              \"outbound\": \"Keluar jika cocok\",\n              \"rule_set\": \"URL set aturan\",\n              \"package_name\": \"Nama paket\",\n              \"process_name\": \"Nama proses\",\n              \"process_path\": \"Jalur proses\",\n              \"network\": \"Jaringan\",\n              \"port_range\": \"Port tujuan\",\n              \"source_port_range\": \"Port sumber\",\n              \"protocol\": \"Protokol\",\n              \"ip_cidr\": \"IP CIDR tujuan\",\n              \"source_ip_cidr\": \"IP CIDR sumber\",\n              \"domain\": \"Domain\",\n              \"domain_suffixe\": \"Sufiks domain\",\n              \"domain_keyword\": \"Kata kunci domain\",\n              \"domain_regex\": \"Regex domain\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"Proxy\",\n              \"direct\": \"Langsung\",\n              \"direct_with_fragment\": \"Langsung dengan fragmen\",\n              \"block\": \"Blokir\"\n            },\n            \"network(map)\": {\n              \"all\": \"Semua\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"Semua\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"Tambah nilai baru\",\n            \"update\": \"Perbarui nilai\",\n            \"clearList\": \"Bersihkan daftar\",\n            \"clearListMsg\": \"Semua item dihapus\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"Aplikasi Android\",\n            \"showSystemApps\": \"Tampilkan aplikasi sistem\",\n            \"hideSystemApps\": \"Sembunyikan aplikasi sistem\",\n            \"clearSelection\": \"Hapus pilihan\",\n            \"uninstalled\": \"Dihapus\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"DNS jarak jauh\",\n        \"remoteDnsDomainStrategy\": \"Strategi domain DNS jarak jauh\",\n        \"directDns\": \"Penyelesai server keluar (langsung)\",\n        \"directDnsDomainStrategy\": \"Strategi domain keluar\",\n        \"enableDnsRouting\": \"Aktifkan perutean DNS\",\n        \"enableFakeDns\": \"Aktifkan DNS palsu\",\n        \"domainStrategy\": {\n          \"auto\": \"Otomatis\",\n          \"preferIpv6\": \"Pilih IPv6\",\n          \"preferIpv4\": \"Pilih IPv4\",\n          \"ipv4Only\": \"Hanya IPv4\",\n          \"ipv6Only\": \"Hanya IPv6\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"Masuk\",\n        \"serviceMode\": \"Mode layanan\",\n        \"serviceModes\": {\n          \"proxy\": \"Hanya layanan proksi\",\n          \"systemProxy\": \"Atur proksi sistem\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"Layanan VPN\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"Proxy\",\n          \"systemProxy\": \"Proxy sistem\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"Layanan VPN\"\n        },\n        \"strictRoute\": \"Rute ketat\",\n        \"tunImplementation\": \"Implementasi TUN\",\n        \"tunImplementations\": {\n          \"mixed\": \"Campuran\",\n          \"system\": \"Sistem\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"Port campuran\",\n        \"tproxyPort\": \"Port proksi transparan\",\n        \"directPort\": \"Port direct\",\n        \"redirectPort\": \"Port pengalihan\",\n        \"allowConnectionFromLan\": \"Bagikan VPN di jaringan lokal\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"Trik TLS\",\n        \"enable\": \"Aktifkan fragmen\",\n        \"packets\": \"Paket Fragmentasi\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"Ukuran fragmen\",\n        \"sleep\": \"Jeda fragmen\",\n        \"mixedSniCase\": {\n          \"enable\": \"Aktifkan kasus SNI campuran\"\n        },\n        \"padding\": {\n          \"enable\": \"Aktifkan padding\",\n          \"size\": \"Ukuran padding\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"Aktifkan WARP\",\n        \"generateConfig\": \"Buat konfigurasi WARP\",\n        \"configGenerated\": \"Konfigurasi WARP dibuat\",\n        \"missingConfig\": \"Konfigurasi WARP hilang\",\n        \"detourMode\": \"Mode Rute WARP\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"Alihkan proksi melalui WARP\",\n          \"warpOverProxy\": \"Alihkan WARP melalui proksi\",\n          \"proxyOverWarpExplain\": \"Buka blokir proksi dengan WARP\",\n          \"warpOverProxyExplain\": \"Keamanan ekstra dengan WARP\"\n        },\n        \"licenseKey\": \"Kunci lisensi\",\n        \"cleanIp\": \"IP bersih\",\n        \"port\": \"Port\",\n        \"noise\": {\n          \"count\": \"Jumlah kebisingan\",\n          \"mode\": \"Mode kebisingan\",\n          \"size\": \"Ukuran kebisingan\",\n          \"delay\": \"Penundaan kebisingan\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"Koneksi\",\n      \"traffic\": \"Lalu lintas\",\n      \"trafficLive\": \"Lalu lintas langsung\",\n      \"trafficTotal\": \"Total lalu lintas\",\n      \"uplink\": \"Unggah\",\n      \"downlink\": \"Unduh\",\n      \"speed\": \"Kecepatan\",\n      \"totalTransferred\": \"Total ditransfer\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"Unggah\",\n      \"download\": \"Unduh\",\n      \"total\": \"Total lalu lintas\",\n      \"expireDate\": \"Tanggal kedaluwarsa\",\n      \"expired\": \"Kedaluwarsa\",\n      \"noTraffic\": \"Kuota habis\",\n      \"remainingTime\": \"Sisa waktu\",\n      \"remainingDuration\": \"tersisa ${duration} hari\",\n      \"remainingDurationNew\": \"${duration} hari\",\n      \"remainingTrafficSemanticLabel\": \"${consumed} dari ${total} lalu lintas terpakai\",\n      \"remainingTraffic\": \"Sisa lalu lintas\",\n      \"remainingUsage\": \"Sisa\",\n      \"profileSite\": \"Penyedia\",\n      \"profileSupport\": \"Dukungan\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"Urut berdasarkan\",\n      \"sort\": {\n        \"name\": \"Menurut abjad\",\n        \"lastUpdate\": \"Terakhir diperbarui\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"Persetujuan Cloudflare WARP\",\n      \"description(rich)\": \"Cloudflare WARP adalah penyedia VPN WireGuard gratis. Dengan mengaktifkan opsi ini, Anda menyetujui ${tos(Ketentuan Layanan)} dan ${privacy(Kebijakan Privasi)} Cloudflare WARP.\"\n    },\n    \"newVersion\": {\n      \"title\": \"Pembaruan tersedia\",\n      \"msg\": \"Versi baru @:common.appTitle tersedia. Apakah Anda ingin memperbarui sekarang?\",\n      \"currentVersion\": \"Versi saat ini: \",\n      \"newVersion\": \"Versi baru: \",\n      \"updateNow\": \"Perbarui sekarang\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"Ini akan menimpa semua opsi konfigurasi dengan nilai yang diberikan. Anda yakin?\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"Hapus profil\",\n          \"msg\": \"Anda yakin ingin menghapus profil ini secara permanen?\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"Meningkatkan pilihan otomatis\",\n          \"msg\": \"Dengan membagikan aplikasi yang dipilih, Anda membantu melengkapi daftar \\\"pilihan otomatis\\\"\"\n        },\n        \"import\": {\n          \"msg\": \"Ini akan menggantikan semua pilihan proksi per aplikasi Anda saat ini. Anda yakin ingin melanjutkan?\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"Hapus aturan\",\n          \"msg\": \"Anda yakin ingin menghapus aturan \\\"$rulename\\\"?\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"Fitur eksperimental sedang digunakan\",\n      \"msg\": \"Anda telah mengaktifkan beberapa fitur eksperimental yang mungkin memengaruhi kualitas koneksi dan menyebabkan kesalahan tak terduga. Anda selalu dapat mengubah atau menyetel ulang opsi ini dari halaman konfigurasi.\",\n      \"disable\": \"Jangan tampilkan lagi\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"Pilih profil\",\n      \"msg\": \"Mari kita mulai dengan menambahkan profil koneksi yang berisi detail koneksi VPN Anda.\\n\\nBelum punya server VPN? Jangan khawatir, ikuti tutorial di bawah ini untuk mengaturnya dengan cepat dan gratis.\",\n      \"helpBtn\": {\n        \"label\": \"Tunjukkan caranya\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"Peringatan tautan eksternal\",\n      \"youAreAboutToVisit\": \"Anda akan mengunjungi:\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"Situs web ini tidak ada dalam daftar tepercaya kami. Harap lanjutkan dengan hati-hati.\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"Tag lengkap:\",\n      \"type\": \"Tipe:\",\n      \"testTime\": \"Waktu uji:\",\n      \"testDelay\": \"Jeda uji:\",\n      \"isSelected\": \"Dipilih:\",\n      \"isGroup\": \"Grup\",\n      \"isSecure\": \"Aman:\",\n      \"port\": \"Port:\",\n      \"host\": \"Host:\",\n      \"ip\": \"IP:\",\n      \"countryCode\": \"Kode negara:\",\n      \"region\": \"Wilayah:\",\n      \"city\": \"Kota:\",\n      \"asn\": \"ASN:\",\n      \"organization\": \"Organisasi:\",\n      \"location\": \"Lokasi:\",\n      \"postalCode\": \"Kode pos:\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"Tanyakan setiap kali\",\n      \"alertMessage\": \"Sembunyikan atau keluar dari aplikasi?\",\n      \"remember\": \"Ingat pilihan saya\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"Ketuk untuk menyambungkan\",\n    \"connect\": \"Sambungkan\",\n    \"connecting\": \"Menyambungkan...\",\n    \"connected\": \"Tersambung\",\n    \"disconnect\": \"Putuskan\",\n    \"disconnecting\": \"Memutuskan...\",\n    \"reconnect\": \"Sambungkan kembali\",\n    \"reconnectMsg\": \"Menyambungkan kembali untuk menerapkan perubahan...\",\n    \"secure\": \"Diamankan oleh WARP\"\n  },\n  \"errors\": {\n    \"unexpected\": \"Kesalahan tak terduga\",\n    \"connection\": {\n      \"unexpected\": \"Kesalahan koneksi tak terduga\",\n      \"timeout\": \"Waktu koneksi habis\",\n      \"badResponse\": \"Respons buruk\",\n      \"connectionError\": \"Kesalahan koneksi\",\n      \"badCertificate\": \"Sertifikat rusak\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"Kesalahan tak terduga\",\n      \"notFound\": \"Profil tidak ditemukan\",\n      \"invalidConfig\": \"Konfigurasi tidak valid\",\n      \"invalidUrl\": \"URL tidak valid\",\n      \"canceledByUser\": \"Dibatalkan oleh pengguna\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"Kegagalan tak terduga\",\n      \"missingVpnPermission\": \"Izin VPN hilang\",\n      \"missingNotificationPermission\": \"Izin notifikasi hilang\",\n      \"core\": \"Kesalahan inti\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"Layanan tidak berjalan\",\n      \"missingPrivilege\": \"Izin hilang\",\n      \"missingPrivilegeMsg\": \"Mode VPN memerlukan izin administrator. Harap mulai ulang aplikasi sebagai administrator atau ubah mode layanan.\",\n      \"invalidConfigOptions\": \"Opsi konfigurasi tidak valid\",\n      \"invalidConfig\": \"Konfigurasi tidak valid\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"Lisensi WARP hilang\",\n      \"missingLicenseMsg\": \"Profil yang dipilih menggunakan fitur WARP. Untuk menggunakan fitur ini, Anda harus menyetujui lisensi WARP.\"\n    }\n  }\n}"
  },
  {
    "path": "assets/translations/pt-BR.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"Hiddify\",\n    \"start\": \"Começar\",\n    \"version\": \"Versão\",\n    \"ok\": \"OK\",\n    \"cancel\": \"Cancelar\",\n    \"kContinue\": \"Continuar\",\n    \"showMore\": \"Mostrar mais\",\n    \"showLess\": \"Mostrar menos\",\n    \"filter\": \"Filtrar\",\n    \"all\": \"Todos\",\n    \"pause\": \"Pausar\",\n    \"resume\": \"Retomar\",\n    \"clear\": \"Limpar\",\n    \"close\": \"Fechar\",\n    \"auto\": \"Automático\",\n    \"manually\": \"Manualmente\",\n    \"name\": \"Nome\",\n    \"url\": \"URL\",\n    \"add\": \"Adicionar\",\n    \"clipboard\": \"Área de transferência\",\n    \"addToClipboard\": \"Adicionar à área de transferência\",\n    \"scanQr\": \"Escanear QR\",\n    \"free\": \"Grátis\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Fragmento\",\n    \"help\": \"Ajuda\",\n    \"save\": \"Salvar\",\n    \"update\": \"Atualizar\",\n    \"share\": \"Compartilhar\",\n    \"edit\": \"Editar\",\n    \"delete\": \"Excluir\",\n    \"discard\": \"Descartar\",\n    \"import\": \"Importar\",\n    \"export\": \"Exportar\",\n    \"later\": \"Mais tarde\",\n    \"ignore\": \"Ignorar\",\n    \"quit\": \"Sair\",\n    \"notSet\": \"Não definido\",\n    \"hide\": \"Ocultar\",\n    \"exit\": \"Sair\",\n    \"reset\": \"Redefinir\",\n    \"done\": \"Concluído\",\n    \"search\": \"Buscar\",\n    \"decline\": \"Recusar\",\n    \"agree\": \"Aceitar\",\n    \"empty\": \"Vazio\",\n    \"unknown\": \"Desconhecido\",\n    \"hidden\": \"Oculto\",\n    \"timeout\": \"Tempo esgotado\",\n    \"sort\": \"Ordenar\",\n    \"dashboard\": \"Painel\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"$n dia\",\n        \"other\": \"$n dias\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"$n hora\",\n        \"other\": \"$n horas\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"Permissão negada\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"Adicionado à área de transferência com sucesso\",\n          \"failure\": \"Falha ao copiar para a área de transferência\",\n          \"contentTooLarge\": \"Conteúdo muito grande. Use a exportação para arquivo\"\n        },\n        \"file\": {\n          \"success\": \"Arquivo JSON criado com sucesso\",\n          \"failure\": \"Falha ao criar o arquivo\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"Confirmar importação\",\n        \"success\": \"Importado com sucesso\",\n        \"failure\": \"Falha ao importar\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"Tudo o que você precisa para uma internet sem restrições\",\n    \"termsAndPolicyCaution(rich)\": \"Ao continuar, você concorda com os ${tap(@:pages.about.termsAndConditions)}\",\n    \"info(rich)\": \"Feito com ❤️ por Hiddify - ${tap_source(Código Aberto)} (${tap_license(Licença)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"Início\",\n      \"quickSettings\": \"Configurações rápidas\"\n    },\n    \"proxies\": {\n      \"title\": \"Proxies\",\n      \"sort\": \"Ordenar proxies\",\n      \"testDelay\": \"Testar latência\",\n      \"empty\": \"Nenhum proxy disponível\",\n      \"activeProxy\": \"Proxy ativo\",\n      \"unknownIp\": \"IP desconhecido\",\n      \"sortOptions\": {\n        \"unsorted\": \"Padrão\",\n        \"name\": \"Alfabeticamente\",\n        \"delay\": \"Por latência\"\n      },\n      \"ipInfo\": {\n        \"address\": \"Endereço de IP\",\n        \"country\": \"País\",\n        \"organization\": \"Organização\"\n      },\n      \"delay\": {\n        \"result\": \"Latência: ${delay}ms\",\n        \"timeout\": \"Tempo limite do teste de latência esgotado\",\n        \"testing\": \"Latência: testando...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"Perfis\",\n      \"add\": \"Adicionar perfil\",\n      \"update\": \"Atualizar perfil\",\n      \"viewAllProfiles\": \"Ver todos os perfis\",\n      \"activeProfileName\": \"Nome do perfil ativo: \\\"${name}\\\".\",\n      \"nonActiveProfileName\": \"Selecionar \\\"${name}\\\" como perfil ativo\",\n      \"freeSubNotFound\": \"Nenhuma assinatura gratuita encontrada\",\n      \"freeSubNotFoundForRegion\": \"Nenhuma assinatura gratuita encontrada para a região \\\"${region}\\\"\",\n      \"failedToLoad\": \"Falha ao carregar\",\n      \"updateSubscriptions\": \"Atualizar assinaturas\",\n      \"share\": {\n        \"urlToClipboard\": \"URL para a área de transferência\",\n        \"showUrlQr\": \"Mostrar QR code da URL\",\n        \"jsonToClipboard\": \"JSON para a área de transferência\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"Perfil salvo com sucesso\"\n        },\n        \"invalidUrl\": \"URL inválida\",\n        \"add\": {\n          \"failure\": \"Falha ao adicionar perfil\"\n        },\n        \"update\": {\n          \"success\": \"Perfil atualizado com sucesso\",\n          \"successNamed\": \"\\\"${name}\\\" atualizado com sucesso\",\n          \"failure\": \"Falha ao atualizar perfil\",\n          \"failureNamed\": \"Falha ao atualizar \\\"${name}\\\"\"\n        },\n        \"delete\": {\n          \"success\": \"Perfil excluído com sucesso\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"Perfil\",\n      \"lastUpdate\": \"Última atualização\",\n      \"form\": {\n        \"nameHint\": \"Nome do perfil\",\n        \"emptyName\": \"O nome é obrigatório\",\n        \"invalidUrl\": \"URL inválida\",\n        \"urlHint\": \"URL de configuração completa\",\n        \"disableAutoUpdate\": \"Desativar atualização automática\",\n        \"autoUpdateInterval\": \"Intervalo de atualização automática\",\n        \"loading\": \"Adicionando perfil...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"Registros\",\n      \"shareCoreLogs\": \"Compartilhar registros do núcleo\",\n      \"shareAppLogs\": \"Compartilhar registros do aplicativo\"\n    },\n    \"about\": {\n      \"title\": \"Sobre\",\n      \"notAvailableMsg\": \"Você já está usando a versão mais recente\",\n      \"checkForUpdate\": \"Verificar atualizações\",\n      \"openWorkingDir\": \"Abrir diretório de trabalho\",\n      \"sourceCode\": \"Código-fonte\",\n      \"telegramChannel\": \"Canal do Telegram\",\n      \"termsAndConditions\": \"Termos e Condições\",\n      \"privacyPolicy\": \"Política de Privacidade\"\n    },\n    \"settings\": {\n      \"title\": \"Configurações\",\n      \"resetTunnel\": \"Redefinir perfil de VPN\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"Importar opções da área de transferência\",\n          \"file\": \"Importar opções de um arquivo\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"Copiar opções anônimas para a área de transferência\",\n          \"anonymousToFile\": \"Exportar opções anônimas para um arquivo\",\n          \"allToClipboard\": \"Copiar todas as opções para a área de transferência\",\n          \"allToFile\": \"Exportar todas as opções para um arquivo\"\n        },\n        \"reset\": \"Redefinir opções\"\n      },\n      \"general\": {\n        \"title\": \"Geral\",\n        \"locale\": \"Idioma\",\n        \"themeMode\": \"Tema\",\n        \"themeModes\": {\n          \"system\": \"Padrão do sistema\",\n          \"dark\": \"Modo escuro\",\n          \"light\": \"Modo claro\",\n          \"black\": \"Modo preto\"\n        },\n        \"enableAnalytics\": \"Ativar análise de dados\",\n        \"enableAnalyticsMsg\": \"Permitir a coleta de dados de análise e relatórios de falhas para melhorar o aplicativo\",\n        \"autoIpCheck\": \"Verificar IP da conexão automaticamente\",\n        \"dynamicNotification\": \"Exibir velocidade na notificação\",\n        \"hapticFeedback\": \"Feedback tátil\",\n        \"actionAtClosing\": \"Ação ao fechar\",\n        \"autoStart\": \"Iniciar com o sistema\",\n        \"silentStart\": \"Iniciar minimizado\",\n        \"ignoreBatteryOptimizations\": \"Desativar otimização de bateria\",\n        \"ignoreBatteryOptimizationsMsg\": \"Remover restrições para um desempenho ideal da VPN\",\n        \"memoryLimit\": \"Limite de memória\",\n        \"memoryLimitMsg\": \"Ative se estiver enfrentando erros de falta de memória ou travamentos frequentes do aplicativo\",\n        \"debugMode\": \"Modo de depuração\",\n        \"debugModeMsg\": \"Reinicie o aplicativo para aplicar esta alteração\",\n        \"logLevel\": \"Nível de registro\",\n        \"connectionTestUrl\": \"URL de teste de conexão\",\n        \"urlTestInterval\": \"Intervalo de teste de URL\",\n        \"clashApiPort\": \"Porta da API do Clash\",\n        \"useXrayCoreWhenPossible\": \"Usar xray-core quando possível\",\n        \"useXrayCoreWhenPossibleMsg\": \"Use o xray-core ao analisar links de assinatura. Você precisa reimportar o link para ativar esta opção\"\n      },\n      \"routing\": {\n        \"title\": \"Roteamento\",\n        \"perAppProxy\": {\n          \"title\": \"Proxy por aplicativo\",\n          \"hideSysApps\": \"Ocultar aplicativos do sistema\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Importar seleção da área de transferência\",\n              \"file\": \"Importar seleção de um arquivo\",\n              \"msg\": \"A importação substituirá suas seleções atuais. Tem certeza de que deseja continuar?\"\n            },\n            \"export\": {\n              \"clipboard\": \"Copiar seleção para a área de transferência\",\n              \"file\": \"Exportar seleção para um arquivo\"\n            },\n            \"shareToAll\": \"Compartilhar com todos\",\n            \"clearAllSelections\": \"Limpar todas as seleções\"\n          },\n          \"modes\": {\n            \"all\": \"Todos\",\n            \"proxy\": \"Proxy\",\n            \"bypass\": \"Ignorar\",\n            \"allMsg\": \"Usar proxy para todos os aplicativos\",\n            \"proxyMsg\": \"Usar proxy apenas para aplicativos selecionados\",\n            \"bypassMsg\": \"Não usar proxy para aplicativos selecionados\"\n          },\n          \"autoSelection\": {\n            \"title\": \"Seleção automática\",\n            \"performNow\": \"Executar agora\",\n            \"resetToDefault\": \"Redefinir para o padrão\",\n            \"autoUpdateInterval\": \"Intervalo de atualização automática\",\n            \"toast\": {\n              \"success\": \"Seleção automática de aplicativos concluída com sucesso\",\n              \"failure\": \"Falha na seleção automática\",\n              \"regionNotFound\": \"Seleção automática não encontrada para a região \\\"${region}\\\"\",\n              \"alreadyInAuto\": \"Suas seleções já estão na lista automática\"\n            },\n            \"dialog\": {\n              \"title\": \"Seleção automática de aplicativos\",\n              \"msg\": \"A função de seleção automática para o proxy por aplicativo foi desativada devido à mudança de região para \\\"${region}\\\"\"\n            }\n          }\n        },\n        \"region\": \"Região\",\n        \"regions\": {\n          \"ir\": \"Irã (ir)\",\n          \"cn\": \"China (cn)\",\n          \"ru\": \"Rússia (ru)\",\n          \"af\": \"Afeganistão (af)\",\n          \"id\": \"Indonésia (id)\",\n          \"tr\": \"Turquia (tr)\",\n          \"br\": \"Brasil (br)\",\n          \"other\": \"Outro\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"Estratégia de Balancer\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"Bloquear anúncios\",\n        \"bypassLan\": \"Ignorar LAN\",\n        \"resolveDestination\": \"Resolver destino\",\n        \"ipv6Route\": \"Rota IPv6\",\n        \"ipv6Modes\": {\n          \"disable\": \"Desativar\",\n          \"enable\": \"Ativar\",\n          \"prefer\": \"Preferencial\",\n          \"only\": \"Exclusivo\"\n        },\n        \"routeRule\": {\n          \"title\": \"Regras de Roteamento\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Importar regras da área de transferência\",\n              \"file\": \"Importar regras de um arquivo\"\n            },\n            \"export\": {\n              \"clipboard\": \"Copiar regras para a área de transferência\",\n              \"file\": \"Salvar regras em um arquivo\"\n            },\n            \"reset\": \"Redefinir regras\"\n          },\n          \"deleteRule\": \"Excluir regra\",\n          \"createRule\": \"Criar nova regra\",\n          \"rule\": {\n            \"title\": \"Regra\",\n            \"ruleChanged\": \"Regra alterada\",\n            \"ruleChangedMsg\": \"Deseja salvar suas edições?\",\n            \"onlyTunMode\": \"Disponível apenas no modo TUN\",\n            \"notAvailabeInThisPlatform\": \"Não disponível nesta plataforma\",\n            \"canNotBeEmpty\": \"Não pode estar vazio\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"\\\"URL\\\" válido como\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe ou google chrome ou chrome\",\n            \"validProcessName\": \"\\\"Nome do Processo\\\" válido como\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"\\\"Caminho do Processo\\\" válido como\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 ou 1-65000\",\n            \"validPortRange\": \"\\\"Porta\\\" ou \\\"Intervalo de Portas\\\" válido como\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 ou 10.0.0.0/24\",\n            \"validIpCidr\": \"IP CIDR válido como\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com ou dl.google.com\",\n            \"validDomain\": \"\\\"Domínio\\\" válido como\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com ou .ir\",\n            \"validDomainSuffix\": \"\\\"Sufixo de Domínio\\\" válido como\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"Nome\",\n              \"outbound\": \"Saída se corresponder\",\n              \"rule_set\": \"URL do conjunto de regras\",\n              \"package_name\": \"Nomes dos pacotes\",\n              \"process_name\": \"Nomes dos processos\",\n              \"process_path\": \"Caminhos dos processos\",\n              \"network\": \"Redes\",\n              \"port_range\": \"Portas de destino\",\n              \"source_port_range\": \"Portas de origem\",\n              \"protocol\": \"Protocolo\",\n              \"ip_cidr\": \"IP CIDR de destino\",\n              \"source_ip_cidr\": \"IP CIDR de origem\",\n              \"domain\": \"Domínio\",\n              \"domain_suffixe\": \"Sufixo de domínio\",\n              \"domain_keyword\": \"Palavra-chave de domínio\",\n              \"domain_regex\": \"Expressão regular de domínio\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"Proxy\",\n              \"direct\": \"Direto\",\n              \"direct_with_fragment\": \"Direto com fragmento\",\n              \"block\": \"Bloquear\"\n            },\n            \"network(map)\": {\n              \"all\": \"Todos\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"Todos\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"Adicionar novo valor\",\n            \"update\": \"Atualizar valor\",\n            \"clearList\": \"Limpar lista\",\n            \"clearListMsg\": \"Todos os itens foram excluídos\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"Aplicativos Android\",\n            \"showSystemApps\": \"Mostrar aplicativos do sistema\",\n            \"hideSystemApps\": \"Ocultar aplicativos do sistema\",\n            \"clearSelection\": \"Limpar seleção\",\n            \"uninstalled\": \"Desinstalado\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"DNS remoto\",\n        \"remoteDnsDomainStrategy\": \"Estratégia de domínio de DNS remoto\",\n        \"directDns\": \"Resolvedor de servidor de saída (direto)\",\n        \"directDnsDomainStrategy\": \"Estratégia de domínio de saída\",\n        \"enableDnsRouting\": \"Ativar roteamento de DNS\",\n        \"enableFakeDns\": \"Ativar DNS falso\",\n        \"domainStrategy\": {\n          \"auto\": \"Automático\",\n          \"preferIpv6\": \"Preferir IPv6\",\n          \"preferIpv4\": \"Preferir IPv4\",\n          \"ipv4Only\": \"Apenas IPv4\",\n          \"ipv6Only\": \"Apenas IPv6\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"Entrada\",\n        \"serviceMode\": \"Modo de serviço\",\n        \"serviceModes\": {\n          \"proxy\": \"Apenas serviço de proxy\",\n          \"systemProxy\": \"Definir proxy do sistema\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"Serviço VPN\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"Proxy\",\n          \"systemProxy\": \"Proxy do sistema\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"Serviço VPN\"\n        },\n        \"strictRoute\": \"Roteamento estrito\",\n        \"tunImplementation\": \"Implementação de TUN\",\n        \"tunImplementations\": {\n          \"mixed\": \"Misto\",\n          \"system\": \"Sistema\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"Porta mista\",\n        \"tproxyPort\": \"Porta de proxy transparente\",\n        \"directPort\": \"Porta de directo\",\n        \"redirectPort\": \"Porta de redirecionamento\",\n        \"allowConnectionFromLan\": \"Compartilhar VPN na rede local\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"Truques de TLS\",\n        \"enable\": \"Ativar fragmento\",\n        \"packets\": \"Pacotes de Fragmentação\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"Tamanho do fragmento\",\n        \"sleep\": \"Atraso do fragmento\",\n        \"mixedSniCase\": {\n          \"enable\": \"Ativar maiúsculas/minúsculas mistas no SNI\"\n        },\n        \"padding\": {\n          \"enable\": \"Ativar preenchimento\",\n          \"size\": \"Tamanho do preenchimento\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"Ativar WARP\",\n        \"generateConfig\": \"Gerar configuração WARP\",\n        \"configGenerated\": \"Configuração WARP gerada\",\n        \"missingConfig\": \"Configuração WARP ausente\",\n        \"detourMode\": \"Modo de Roteamento WARP\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"Desviar proxies através do WARP\",\n          \"warpOverProxy\": \"Desviar WARP através de proxies\",\n          \"proxyOverWarpExplain\": \"Desbloquear proxies com WARP\",\n          \"warpOverProxyExplain\": \"Segurança extra com WARP\"\n        },\n        \"licenseKey\": \"Chave de licença\",\n        \"cleanIp\": \"IP limpo\",\n        \"port\": \"Porta\",\n        \"noise\": {\n          \"count\": \"Contagem de ruído\",\n          \"mode\": \"Modo de ruído\",\n          \"size\": \"Tamanho do ruído\",\n          \"delay\": \"Atraso do ruído\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"Conexão\",\n      \"traffic\": \"Tráfego\",\n      \"trafficLive\": \"Tráfego ao vivo\",\n      \"trafficTotal\": \"Tráfego total\",\n      \"uplink\": \"Envio\",\n      \"downlink\": \"Recebimento\",\n      \"speed\": \"Velocidade\",\n      \"totalTransferred\": \"Total transferido\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"Upload\",\n      \"download\": \"Download\",\n      \"total\": \"Tráfego total\",\n      \"expireDate\": \"Data de validade\",\n      \"expired\": \"Expirado\",\n      \"noTraffic\": \"Cota esgotada\",\n      \"remainingTime\": \"Tempo restante\",\n      \"remainingDuration\": \"${duration} dias restantes\",\n      \"remainingDurationNew\": \"${duration} dias\",\n      \"remainingTrafficSemanticLabel\": \"${consumed} de ${total} de tráfego consumido\",\n      \"remainingTraffic\": \"Tráfego restante\",\n      \"remainingUsage\": \"Restante\",\n      \"profileSite\": \"Provedor\",\n      \"profileSupport\": \"Suporte\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"Ordenar por\",\n      \"sort\": {\n        \"name\": \"Alfabeticamente\",\n        \"lastUpdate\": \"Última atualização\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"Consentimento do Cloudflare WARP\",\n      \"description(rich)\": \"O Cloudflare WARP é um provedor de VPN WireGuard gratuito. Ao ativar esta opção, você concorda com os ${tos(Termos de Serviço)} e a ${privacy(Política de Privacidade)} do Cloudflare WARP.\"\n    },\n    \"newVersion\": {\n      \"title\": \"Atualização disponível\",\n      \"msg\": \"Uma nova versão do @:common.appTitle está disponível. Deseja atualizar agora?\",\n      \"currentVersion\": \"Versão atual: \",\n      \"newVersion\": \"Nova versão: \",\n      \"updateNow\": \"Atualizar agora\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"Isso substituirá todas as opções de configuração pelos valores fornecidos. Você tem certeza?\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"Excluir perfil\",\n          \"msg\": \"Tem certeza de que deseja excluir este perfil permanentemente?\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"Melhorando a seleção automática\",\n          \"msg\": \"Ao compartilhar os aplicativos selecionados, você ajuda a completar a lista de \\\"seleção automática\\\"\"\n        },\n        \"import\": {\n          \"msg\": \"Isso substituirá todas as suas seleções atuais de proxy por aplicativo. Tem certeza de que deseja continuar?\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"Excluir regra\",\n          \"msg\": \"Tem certeza de que deseja excluir a regra \\\"$rulename\\\"?\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"Recursos experimentais em uso\",\n      \"msg\": \"Você ativou alguns recursos experimentais que podem afetar a qualidade da conexão e causar erros inesperados. Você sempre pode alterar ou redefinir essas opções na página de configurações.\",\n      \"disable\": \"Não mostrar novamente\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"Escolha um perfil\",\n      \"msg\": \"Para começar, adicione um perfil de conexão que inclua os detalhes da sua conexão VPN.\\n\\nAinda não tem um servidor VPN? Não se preocupe, siga o tutorial abaixo para configurar um rapidamente e de graça.\",\n      \"helpBtn\": {\n        \"label\": \"Mostre-me como\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"Aviso de link externo\",\n      \"youAreAboutToVisit\": \"Você está prestes a visitar:\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"Este site não está na nossa lista de confiança. Prossiga com cautela.\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"Tag completa:\",\n      \"type\": \"Tipo:\",\n      \"testTime\": \"Hora do teste:\",\n      \"testDelay\": \"Latência do teste:\",\n      \"isSelected\": \"Selecionado:\",\n      \"isGroup\": \"É um grupo\",\n      \"isSecure\": \"É seguro:\",\n      \"port\": \"Porta:\",\n      \"host\": \"Host:\",\n      \"ip\": \"IP:\",\n      \"countryCode\": \"Código do país:\",\n      \"region\": \"Região:\",\n      \"city\": \"Cidade:\",\n      \"asn\": \"ASN:\",\n      \"organization\": \"Organização:\",\n      \"location\": \"Localização:\",\n      \"postalCode\": \"Código postal:\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"Perguntar sempre\",\n      \"alertMessage\": \"Ocultar ou sair do aplicativo?\",\n      \"remember\": \"Lembrar minha escolha\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"Toque para conectar\",\n    \"connect\": \"Conectar\",\n    \"connecting\": \"Conectando...\",\n    \"connected\": \"Conectado\",\n    \"disconnect\": \"Desconectar\",\n    \"disconnecting\": \"Desconectando...\",\n    \"reconnect\": \"Reconectar\",\n    \"reconnectMsg\": \"Reconectando para aplicar as alterações...\",\n    \"secure\": \"Protegido por WARP\"\n  },\n  \"errors\": {\n    \"unexpected\": \"Erro inesperado\",\n    \"connection\": {\n      \"unexpected\": \"Erro de conexão inesperado\",\n      \"timeout\": \"Tempo limite de conexão esgotado\",\n      \"badResponse\": \"Resposta inválida\",\n      \"connectionError\": \"Erro de conexão\",\n      \"badCertificate\": \"Certificado inválido\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"Erro inesperado\",\n      \"notFound\": \"Perfil não encontrado\",\n      \"invalidConfig\": \"Configurações inválidas\",\n      \"invalidUrl\": \"URL inválida\",\n      \"canceledByUser\": \"Cancelado pelo usuário\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"Falha inesperada\",\n      \"missingVpnPermission\": \"Permissão de VPN ausente\",\n      \"missingNotificationPermission\": \"Permissão de notificação ausente\",\n      \"core\": \"Erro no núcleo\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"O serviço não está em execução\",\n      \"missingPrivilege\": \"Permissão ausente\",\n      \"missingPrivilegeMsg\": \"O modo VPN requer privilégios de administrador. Reinicie o aplicativo como administrador ou altere o modo de serviço.\",\n      \"invalidConfigOptions\": \"Opções de configuração inválidas\",\n      \"invalidConfig\": \"Configuração inválida\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"Licença do WARP ausente\",\n      \"missingLicenseMsg\": \"O perfil selecionado usa o recurso WARP. Para usar este recurso, você deve concordar com a licença do WARP.\"\n    }\n  }\n}"
  },
  {
    "path": "assets/translations/ru.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"Hiddify\",\n    \"start\": \"Начать\",\n    \"version\": \"Версия\",\n    \"ok\": \"OK\",\n    \"cancel\": \"Отмена\",\n    \"kContinue\": \"Продолжить\",\n    \"showMore\": \"Показать больше\",\n    \"showLess\": \"Показать меньше\",\n    \"filter\": \"Фильтр\",\n    \"all\": \"Все\",\n    \"pause\": \"Пауза\",\n    \"resume\": \"Возобновить\",\n    \"clear\": \"Очистить\",\n    \"close\": \"Закрыть\",\n    \"auto\": \"Авто\",\n    \"manually\": \"Вручную\",\n    \"name\": \"Имя\",\n    \"url\": \"URL\",\n    \"add\": \"Добавить\",\n    \"clipboard\": \"Буфер обмена\",\n    \"addToClipboard\": \"Добавить в буфер обмена\",\n    \"scanQr\": \"Сканировать QR\",\n    \"free\": \"Бесплатно\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Фрагмент\",\n    \"help\": \"Справка\",\n    \"save\": \"Сохранить\",\n    \"update\": \"Обновить\",\n    \"share\": \"Поделиться\",\n    \"edit\": \"Изменить\",\n    \"delete\": \"Удалить\",\n    \"discard\": \"Отменить\",\n    \"import\": \"Импорт\",\n    \"export\": \"Экспорт\",\n    \"later\": \"Позже\",\n    \"ignore\": \"Игнорировать\",\n    \"quit\": \"Выход\",\n    \"notSet\": \"Не задано\",\n    \"hide\": \"Скрыть\",\n    \"exit\": \"Выйти\",\n    \"reset\": \"Сброс\",\n    \"done\": \"Готово\",\n    \"search\": \"Поиск\",\n    \"decline\": \"Отклонить\",\n    \"agree\": \"Согласен\",\n    \"empty\": \"Пусто\",\n    \"unknown\": \"Неизвестно\",\n    \"hidden\": \"Скрытый\",\n    \"timeout\": \"Тайм-аут\",\n    \"sort\": \"Сортировать\",\n    \"dashboard\": \"Панель управления\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"$n день\",\n        \"few\": \"$n дня\",\n        \"many\": \"$n дней\",\n        \"other\": \"$n дня\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"$n час\",\n        \"few\": \"$n часа\",\n        \"many\": \"$n часов\",\n        \"other\": \"$n часа\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"Доступ запрещен\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"Успешно добавлено в буфер обмена\",\n          \"failure\": \"Не удалось скопировать в буфер обмена\",\n          \"contentTooLarge\": \"Слишком большой контент. Используйте экспорт в файл\"\n        },\n        \"file\": {\n          \"success\": \"Файл JSON успешно создан\",\n          \"failure\": \"Не удалось создать файл\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"Подтвердить импорт\",\n        \"success\": \"Успешно импортировано\",\n        \"failure\": \"Не удалось импортировать\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"Все, что вам нужно для интернета без ограничений\",\n    \"termsAndPolicyCaution(rich)\": \"Продолжая, вы соглашаетесь с ${tap(@:pages.about.termsAndConditions)}\",\n    \"info(rich)\": \"Сделано с ❤️ Hiddify - ${tap_source(Открытый исходный код)} (${tap_license(Лицензия)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"Главная\",\n      \"quickSettings\": \"Быстрые настройки\"\n    },\n    \"proxies\": {\n      \"title\": \"Прокси\",\n      \"sort\": \"Сортировать прокси\",\n      \"testDelay\": \"Проверить задержку\",\n      \"empty\": \"Нет доступных прокси\",\n      \"activeProxy\": \"Активный прокси\",\n      \"unknownIp\": \"Неизвестный IP\",\n      \"sortOptions\": {\n        \"unsorted\": \"По умолчанию\",\n        \"name\": \"По алфавиту\",\n        \"delay\": \"По задержке\"\n      },\n      \"ipInfo\": {\n        \"address\": \"IP-адрес\",\n        \"country\": \"Страна\",\n        \"organization\": \"Организация\"\n      },\n      \"delay\": {\n        \"result\": \"Задержка: ${delay} мс\",\n        \"timeout\": \"Тайм-аут теста задержки\",\n        \"testing\": \"Задержка: тестирование...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"Профили\",\n      \"add\": \"Добавить профиль\",\n      \"update\": \"Обновить профиль\",\n      \"viewAllProfiles\": \"Посмотреть все профили\",\n      \"activeProfileName\": \"Имя активного профиля: \\\"${name}\\\".\",\n      \"nonActiveProfileName\": \"Выбрать \\\"${name}\\\" как активный профиль\",\n      \"freeSubNotFound\": \"Бесплатная подписка не найдена\",\n      \"freeSubNotFoundForRegion\": \"Бесплатная подписка для региона \\\"${region}\\\" не найдена\",\n      \"failedToLoad\": \"Не удалось загрузить\",\n      \"updateSubscriptions\": \"Обновить подписки\",\n      \"share\": {\n        \"urlToClipboard\": \"URL в буфер обмена\",\n        \"showUrlQr\": \"Показать QR-код URL\",\n        \"jsonToClipboard\": \"JSON в буфер обмена\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"Профиль успешно сохранен\"\n        },\n        \"invalidUrl\": \"Неверный URL\",\n        \"add\": {\n          \"failure\": \"Не удалось добавить профиль\"\n        },\n        \"update\": {\n          \"success\": \"Профиль успешно обновлен\",\n          \"successNamed\": \"\\\"${name}\\\" успешно обновлен\",\n          \"failure\": \"Не удалось обновить профиль\",\n          \"failureNamed\": \"Не удалось обновить \\\"${name}\\\"\"\n        },\n        \"delete\": {\n          \"success\": \"Профиль успешно удален\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"Профиль\",\n      \"lastUpdate\": \"Последнее обновление\",\n      \"form\": {\n        \"nameHint\": \"Имя профиля\",\n        \"emptyName\": \"Имя обязательно для заполнения\",\n        \"invalidUrl\": \"Неверный URL\",\n        \"urlHint\": \"Полный URL конфигурации\",\n        \"disableAutoUpdate\": \"Отключить автообновление\",\n        \"autoUpdateInterval\": \"Интервал автообновления\",\n        \"loading\": \"Добавление профиля...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"Логи\",\n      \"shareCoreLogs\": \"Поделиться логами ядра\",\n      \"shareAppLogs\": \"Поделиться логами приложения\"\n    },\n    \"about\": {\n      \"title\": \"О программе\",\n      \"notAvailableMsg\": \"Вы уже используете последнюю версию\",\n      \"checkForUpdate\": \"Проверить обновления\",\n      \"openWorkingDir\": \"Открыть рабочую папку\",\n      \"sourceCode\": \"Исходный код\",\n      \"telegramChannel\": \"Канал в Telegram\",\n      \"termsAndConditions\": \"Условия использования\",\n      \"privacyPolicy\": \"Политика конфиденциальности\"\n    },\n    \"settings\": {\n      \"title\": \"Настройки\",\n      \"resetTunnel\": \"Сбросить профиль VPN\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"Импортировать настройки из буфера обмена\",\n          \"file\": \"Импортировать настройки из файла\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"Копировать анонимные настройки в буфер обмена\",\n          \"anonymousToFile\": \"Экспортировать анонимные настройки в файл\",\n          \"allToClipboard\": \"Копировать все настройки в буфер обмена\",\n          \"allToFile\": \"Экспортировать все настройки в файл\"\n        },\n        \"reset\": \"Сбросить настройки\"\n      },\n      \"general\": {\n        \"title\": \"Общие\",\n        \"locale\": \"Язык\",\n        \"themeMode\": \"Тема оформления\",\n        \"themeModes\": {\n          \"system\": \"Системная\",\n          \"dark\": \"Темная\",\n          \"light\": \"Светлая\",\n          \"black\": \"Черная\"\n        },\n        \"enableAnalytics\": \"Включить аналитику\",\n        \"enableAnalyticsMsg\": \"Разрешить сбор аналитики и отправку отчетов о сбоях для улучшения приложения\",\n        \"autoIpCheck\": \"Автоматически проверять IP-адрес\",\n        \"dynamicNotification\": \"Отображать скорость в уведомлении\",\n        \"hapticFeedback\": \"Тактильный отклик\",\n        \"actionAtClosing\": \"Действие при закрытии\",\n        \"autoStart\": \"Запускать при входе в систему\",\n        \"silentStart\": \"Запускать свернутым\",\n        \"ignoreBatteryOptimizations\": \"Отключить оптимизацию батареи\",\n        \"ignoreBatteryOptimizationsMsg\": \"Снять ограничения для оптимальной работы VPN\",\n        \"memoryLimit\": \"Ограничение памяти\",\n        \"memoryLimitMsg\": \"Включите, если вы сталкиваетесь с ошибками нехватки памяти или частыми сбоями приложения\",\n        \"debugMode\": \"Режим отладки\",\n        \"debugModeMsg\": \"Перезапустите приложение, чтобы применить это изменение\",\n        \"logLevel\": \"Уровень логирования\",\n        \"connectionTestUrl\": \"URL для теста соединения\",\n        \"urlTestInterval\": \"Интервал теста URL\",\n        \"clashApiPort\": \"Порт Clash API\",\n        \"useXrayCoreWhenPossible\": \"Использовать xray-core, если возможно\",\n        \"useXrayCoreWhenPossibleMsg\": \"Использовать xray-core при обработке ссылок на подписку. Необходимо повторно импортировать ссылку, чтобы включить эту опцию.\"\n      },\n      \"routing\": {\n        \"title\": \"Маршрутизация\",\n        \"perAppProxy\": {\n          \"title\": \"Прокси для приложений\",\n          \"hideSysApps\": \"Скрыть системные приложения\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Импортировать выбор из буфера обмена\",\n              \"file\": \"Импортировать выбор из файла\",\n              \"msg\": \"Импорт заменит ваш текущий выбор. Вы уверены, что хотите продолжить?\"\n            },\n            \"export\": {\n              \"clipboard\": \"Копировать выбор в буфер обмена\",\n              \"file\": \"Экспортировать выбор в файл\"\n            },\n            \"shareToAll\": \"Поделиться со всеми\",\n            \"clearAllSelections\": \"Очистить весь выбор\"\n          },\n          \"modes\": {\n            \"all\": \"Все\",\n            \"proxy\": \"Прокси\",\n            \"bypass\": \"В обход\",\n            \"allMsg\": \"Проксировать все приложения\",\n            \"proxyMsg\": \"Проксировать только выбранные приложения\",\n            \"bypassMsg\": \"Не проксировать выбранные приложения\"\n          },\n          \"autoSelection\": {\n            \"title\": \"Автовыбор\",\n            \"performNow\": \"Выполнить сейчас\",\n            \"resetToDefault\": \"Сбросить по умолчанию\",\n            \"autoUpdateInterval\": \"Интервал автообновления\",\n            \"toast\": {\n              \"success\": \"Автовыбор приложений успешно завершен\",\n              \"failure\": \"Ошибка автовыбора\",\n              \"regionNotFound\": \"Автовыбор для региона \\\"${region}\\\" не найден\",\n              \"alreadyInAuto\": \"Ваш выбор уже находится в списке автовыбора\"\n            },\n            \"dialog\": {\n              \"title\": \"Автовыбор приложений\",\n              \"msg\": \"Функция автовыбора для прокси приложений была отключена из-за смены региона на \\\"${region}\\\"\"\n            }\n          }\n        },\n        \"region\": \"Регион\",\n        \"regions\": {\n          \"ir\": \"Иран (ir)\",\n          \"cn\": \"Китай (cn)\",\n          \"ru\": \"Россия (ru)\",\n          \"af\": \"Афганистан (af)\",\n          \"id\": \"Индонезия (id)\",\n          \"tr\": \"Турция (tr)\",\n          \"br\": \"Бразилия (br)\",\n          \"other\": \"Другой\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"Стратегия Balancer\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"Блокировать рекламу\",\n        \"bypassLan\": \"Обход LAN\",\n        \"resolveDestination\": \"Определять адрес назначения\",\n        \"ipv6Route\": \"Маршрут IPv6\",\n        \"ipv6Modes\": {\n          \"disable\": \"Отключить\",\n          \"enable\": \"Включить\",\n          \"prefer\": \"Предпочтительно\",\n          \"only\": \"Только\"\n        },\n        \"routeRule\": {\n          \"title\": \"Правила маршрутизации\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Импортировать правила из буфера обмена\",\n              \"file\": \"Импортировать правила из файла\"\n            },\n            \"export\": {\n              \"clipboard\": \"Копировать правила в буфер обмена\",\n              \"file\": \"Сохранить правила в файл\"\n            },\n            \"reset\": \"Сбросить правила\"\n          },\n          \"deleteRule\": \"Удалить правило\",\n          \"createRule\": \"Создать новое правило\",\n          \"rule\": {\n            \"title\": \"Правило\",\n            \"ruleChanged\": \"Правило изменено\",\n            \"ruleChangedMsg\": \"Вы хотите сохранить изменения?\",\n            \"onlyTunMode\": \"Доступно только в режиме TUN\",\n            \"notAvailabeInThisPlatform\": \"Недоступно на этой платформе\",\n            \"canNotBeEmpty\": \"Не может быть пустым\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"Валидный \\\"URL\\\", например\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe или google chrome или chrome\",\n            \"validProcessName\": \"Валидное \\\"Имя процесса\\\", например\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"Валидный \\\"Путь к процессу\\\", например\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 или 1-65000\",\n            \"validPortRange\": \"Валидный \\\"Порт\\\" или \\\"Диапазон портов\\\", например\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 или 10.0.0.0/24\",\n            \"validIpCidr\": \"Валидный IP CIDR, например\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com или dl.google.com\",\n            \"validDomain\": \"Валидный \\\"Домен\\\", например\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com или .ru\",\n            \"validDomainSuffix\": \"Валидный \\\"Суффикс домена\\\", например\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"Имя\",\n              \"outbound\": \"Исходящий при совпадении\",\n              \"rule_set\": \"URL набора правил\",\n              \"package_name\": \"Имена пакетов\",\n              \"process_name\": \"Имена процессов\",\n              \"process_path\": \"Пути к процессам\",\n              \"network\": \"Сети\",\n              \"port_range\": \"Порты назначения\",\n              \"source_port_range\": \"Исходные порты\",\n              \"protocol\": \"Протокол\",\n              \"ip_cidr\": \"IP CIDR назначения\",\n              \"source_ip_cidr\": \"Исходный IP CIDR\",\n              \"domain\": \"Домен\",\n              \"domain_suffixe\": \"Суффикс домена\",\n              \"domain_keyword\": \"Ключевое слово домена\",\n              \"domain_regex\": \"Регулярное выражение домена\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"Прокси\",\n              \"direct\": \"Напрямую\",\n              \"direct_with_fragment\": \"Напрямую с фрагментом\",\n              \"block\": \"Блокировать\"\n            },\n            \"network(map)\": {\n              \"all\": \"Все\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"Все\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"Добавить новое значение\",\n            \"update\": \"Обновить значение\",\n            \"clearList\": \"Очистить список\",\n            \"clearListMsg\": \"Все элементы удалены\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"Приложения Android\",\n            \"showSystemApps\": \"Показать системные приложения\",\n            \"hideSystemApps\": \"Скрыть системные приложения\",\n            \"clearSelection\": \"Очистить выбор\",\n            \"uninstalled\": \"Удалено\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"Удаленный DNS\",\n        \"remoteDnsDomainStrategy\": \"Стратегия домена удаленного DNS\",\n        \"directDns\": \"Распознаватель исходящего сервера (напрямую)\",\n        \"directDnsDomainStrategy\": \"Стратегия исходящего домена\",\n        \"enableDnsRouting\": \"Включить маршрутизацию DNS\",\n        \"enableFakeDns\": \"Включить поддельный DNS\",\n        \"domainStrategy\": {\n          \"auto\": \"Авто\",\n          \"preferIpv6\": \"Предпочитать IPv6\",\n          \"preferIpv4\": \"Предпочитать IPv4\",\n          \"ipv4Only\": \"Только IPv4\",\n          \"ipv6Only\": \"Только IPv6\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"Входящие\",\n        \"serviceMode\": \"Режим службы\",\n        \"serviceModes\": {\n          \"proxy\": \"Только прокси-служба\",\n          \"systemProxy\": \"Установить системный прокси\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"Служба VPN\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"Прокси\",\n          \"systemProxy\": \"Системный прокси\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"Служба VPN\"\n        },\n        \"strictRoute\": \"Строгая маршрутизация\",\n        \"tunImplementation\": \"Реализация TUN\",\n        \"tunImplementations\": {\n          \"mixed\": \"Смешанная\",\n          \"system\": \"Системная\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"Смешанный порт\",\n        \"tproxyPort\": \"Порт прозрачного прокси\",\n        \"directPort\": \"Локальный порт direct\",\n        \"redirectPort\": \"Порт перенаправления\",\n        \"allowConnectionFromLan\": \"Поделиться VPN в локальной сети\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"Трюки TLS\",\n        \"enable\": \"Включить фрагментацию\",\n        \"packets\": \"Пакеты фрагментации\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"Размер фрагмента\",\n        \"sleep\": \"Задержка фрагмента\",\n        \"mixedSniCase\": {\n          \"enable\": \"Включить смешанный регистр SNI\"\n        },\n        \"padding\": {\n          \"enable\": \"Включить дополнение\",\n          \"size\": \"Размер дополнения\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"Включить WARP\",\n        \"generateConfig\": \"Сгенерировать конфигурацию WARP\",\n        \"configGenerated\": \"Конфигурация Warp сгенерирована\",\n        \"missingConfig\": \"Отсутствует конфигурация WARP\",\n        \"detourMode\": \"Режим маршрутизации WARP\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"Направлять прокси через WARP\",\n          \"warpOverProxy\": \"Направлять WARP через прокси\",\n          \"proxyOverWarpExplain\": \"Разблокировать прокси с помощью WARP\",\n          \"warpOverProxyExplain\": \"Дополнительная безопасность с WARP\"\n        },\n        \"licenseKey\": \"Лицензионный ключ\",\n        \"cleanIp\": \"Чистый IP\",\n        \"port\": \"Порт\",\n        \"noise\": {\n          \"count\": \"Количество шума\",\n          \"mode\": \"Режим шума\",\n          \"size\": \"Размер шума\",\n          \"delay\": \"Задержка шума\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"Соединение\",\n      \"traffic\": \"Трафик\",\n      \"trafficLive\": \"Текущий трафик\",\n      \"trafficTotal\": \"Общий трафик\",\n      \"uplink\": \"Отправка\",\n      \"downlink\": \"Прием\",\n      \"speed\": \"Скорость\",\n      \"totalTransferred\": \"Всего передано\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"Отправлено\",\n      \"download\": \"Получено\",\n      \"total\": \"Всего трафика\",\n      \"expireDate\": \"Дата окончания\",\n      \"expired\": \"Истек\",\n      \"noTraffic\": \"Квота исчерпана\",\n      \"remainingTime\": \"Оставшееся время\",\n      \"remainingDuration\": \"осталось ${duration} дней\",\n      \"remainingDurationNew\": \"${duration} дней\",\n      \"remainingTrafficSemanticLabel\": \"израсходовано ${consumed} из ${total} трафика\",\n      \"remainingTraffic\": \"Оставшийся трафик\",\n      \"remainingUsage\": \"Осталось\",\n      \"profileSite\": \"Провайдер\",\n      \"profileSupport\": \"Поддержка\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"Сортировать по\",\n      \"sort\": {\n        \"name\": \"По алфавиту\",\n        \"lastUpdate\": \"Последнему обновлению\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"Соглашение о WARP от Cloudflare\",\n      \"description(rich)\": \"Cloudflare WARP - это бесплатный провайдер WireGuard VPN. Включая эту опцию, вы соглашаетесь с ${tos(Условиями обслуживания)} и ${privacy(Политикой конфиденциальности)} Cloudflare WARP.\"\n    },\n    \"newVersion\": {\n      \"title\": \"Доступно обновление\",\n      \"msg\": \"Доступна новая версия @:common.appTitle. Хотите обновить сейчас?\",\n      \"currentVersion\": \"Текущая версия: \",\n      \"newVersion\": \"Новая версия: \",\n      \"updateNow\": \"Обновить сейчас\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"Это перезапишет все параметры конфигурации предоставленными значениями. Вы уверены?\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"Удалить профиль\",\n          \"msg\": \"Вы уверены, что хотите навсегда удалить этот профиль?\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"Улучшение автовыбора\",\n          \"msg\": \"Делясь выбранными приложениями, вы помогаете пополнить список \\\"автовыбора\\\"\"\n        },\n        \"import\": {\n          \"msg\": \"Это заменит все ваши текущие настройки прокси для приложений. Вы уверены, что хотите продолжить?\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"Удалить правило\",\n          \"msg\": \"Вы уверены, что хотите удалить правило \\\"$rulename\\\"?\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"Используются экспериментальные функции\",\n      \"msg\": \"Вы включили некоторые экспериментальные функции, которые могут повлиять на качество соединения и вызвать непредвиденные ошибки. Вы всегда можете изменить или сбросить эти параметры на странице настроек.\",\n      \"disable\": \"Больше не показывать\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"Выберите профиль\",\n      \"msg\": \"Давайте начнем с добавления профиля подключения, который содержит данные вашего VPN-соединения.\\n\\nЕще нет VPN-сервера? Не беспокойтесь — просто следуйте руководству ниже, чтобы быстро и бесплатно настроить его.\",\n      \"helpBtn\": {\n        \"label\": \"Покажите, как\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"Предупреждение о внешней ссылке\",\n      \"youAreAboutToVisit\": \"Вы собираетесь перейти на сайт:\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"Этот сайт не входит в наш список доверенных. Пожалуйста, действуйте с осторожностью.\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"Полный тег:\",\n      \"type\": \"Тип:\",\n      \"testTime\": \"Время теста:\",\n      \"testDelay\": \"Задержка теста:\",\n      \"isSelected\": \"Выбран:\",\n      \"isGroup\": \"Это группа\",\n      \"isSecure\": \"Защищено:\",\n      \"port\": \"Порт:\",\n      \"host\": \"Хост:\",\n      \"ip\": \"IP:\",\n      \"countryCode\": \"Код страны:\",\n      \"region\": \"Регион:\",\n      \"city\": \"Город:\",\n      \"asn\": \"ASN:\",\n      \"organization\": \"Организация:\",\n      \"location\": \"Местоположение:\",\n      \"postalCode\": \"Почтовый индекс:\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"Спрашивать каждый раз\",\n      \"alertMessage\": \"Скрыть или выйти из приложения?\",\n      \"remember\": \"Запомнить мой выбор\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"Нажмите для подключения\",\n    \"connect\": \"Подключить\",\n    \"connecting\": \"Подключение...\",\n    \"connected\": \"Подключено\",\n    \"disconnect\": \"Отключить\",\n    \"disconnecting\": \"Отключение...\",\n    \"reconnect\": \"Переподключить\",\n    \"reconnectMsg\": \"Переподключение для учета изменений...\",\n    \"secure\": \"Защищено с помощью WARP\"\n  },\n  \"errors\": {\n    \"unexpected\": \"Непредвиденная ошибка\",\n    \"connection\": {\n      \"unexpected\": \"Непредвиденная ошибка подключения\",\n      \"timeout\": \"Тайм-аут подключения\",\n      \"badResponse\": \"Неверный ответ\",\n      \"connectionError\": \"Ошибка подключения\",\n      \"badCertificate\": \"Недействительный сертификат\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"Непредвиденная ошибка\",\n      \"notFound\": \"Профиль не найден\",\n      \"invalidConfig\": \"Неверная конфигурация\",\n      \"invalidUrl\": \"Неверный URL\",\n      \"canceledByUser\": \"Отменено пользователем\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"Непредвиденный сбой\",\n      \"missingVpnPermission\": \"Отсутствует разрешение на VPN\",\n      \"missingNotificationPermission\": \"Отсутствует разрешение на уведомления\",\n      \"core\": \"Ошибка ядра\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"Служба не запущена\",\n      \"missingPrivilege\": \"Отсутствуют права\",\n      \"missingPrivilegeMsg\": \"Режим VPN требует прав администратора. Либо перезапустите приложение от имени администратора, либо измените режим службы.\",\n      \"invalidConfigOptions\": \"Неверные параметры конфигурации\",\n      \"invalidConfig\": \"Неверная конфигурация\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"Отсутствует лицензия Warp\",\n      \"missingLicenseMsg\": \"Выбранный профиль использует функцию WARP; для использования этой функции необходимо принять лицензию WARP.\"\n    }\n  }\n}"
  },
  {
    "path": "assets/translations/tr.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"Hiddify\",\n    \"start\": \"Başlat\",\n    \"version\": \"Sürüm\",\n    \"ok\": \"Tamam\",\n    \"cancel\": \"İptal\",\n    \"kContinue\": \"Devam et\",\n    \"showMore\": \"Daha fazla göster\",\n    \"showLess\": \"Daha az göster\",\n    \"filter\": \"Filtrele\",\n    \"all\": \"Tümü\",\n    \"pause\": \"Duraklat\",\n    \"resume\": \"Devam et\",\n    \"clear\": \"Temizle\",\n    \"close\": \"Kapat\",\n    \"auto\": \"Otomatik\",\n    \"manually\": \"Manuel\",\n    \"name\": \"İsim\",\n    \"url\": \"URL\",\n    \"add\": \"Ekle\",\n    \"clipboard\": \"Pano\",\n    \"addToClipboard\": \"Panoya ekle\",\n    \"scanQr\": \"QR Tara\",\n    \"free\": \"Ücretsiz\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Fragment\",\n    \"help\": \"Yardım\",\n    \"save\": \"Kaydet\",\n    \"update\": \"Güncelle\",\n    \"share\": \"Paylaş\",\n    \"edit\": \"Düzenle\",\n    \"delete\": \"Sil\",\n    \"discard\": \"Vazgeç\",\n    \"import\": \"İçe aktar\",\n    \"export\": \"Dışa aktar\",\n    \"later\": \"Daha sonra\",\n    \"ignore\": \"Yoksay\",\n    \"quit\": \"Çık\",\n    \"notSet\": \"Ayarlanmadı\",\n    \"hide\": \"Gizle\",\n    \"exit\": \"Çıkış\",\n    \"reset\": \"Sıfırla\",\n    \"done\": \"Bitti\",\n    \"search\": \"Ara\",\n    \"decline\": \"Reddet\",\n    \"agree\": \"Kabul et\",\n    \"empty\": \"Boş\",\n    \"unknown\": \"Bilinmeyen\",\n    \"hidden\": \"Gizli\",\n    \"timeout\": \"Zaman aşımı\",\n    \"sort\": \"Sırala\",\n    \"dashboard\": \"Gösterge Paneli\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"$n gün\",\n        \"other\": \"$n gün\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"$n saat\",\n        \"other\": \"$n saat\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"İzin reddedildi\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"Panoya başarıyla eklendi\",\n          \"failure\": \"Panoya kopyalanamadı\",\n          \"contentTooLarge\": \"İçerik çok büyük. Bunun yerine dosyaya aktarmayı kullanın\"\n        },\n        \"file\": {\n          \"success\": \"JSON dosyası başarıyla oluşturuldu\",\n          \"failure\": \"Dosya oluşturulamadı\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"İçe aktarmayı onayla\",\n        \"success\": \"Başarıyla içe aktarıldı\",\n        \"failure\": \"İçe aktarılamadı\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"Sınırsız bir internet için ihtiyacınız olan her şey\",\n    \"termsAndPolicyCaution(rich)\": \"Devam ederek ${tap(@:pages.about.termsAndConditions)} kabul etmiş olursunuz\",\n    \"info(rich)\": \"Hiddify tarafından ❤️ ile yapıldı - ${tap_source(Açık Kaynak)} (${tap_license(Lisans)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"Ana Sayfa\",\n      \"quickSettings\": \"Hızlı ayarlar\"\n    },\n    \"proxies\": {\n      \"title\": \"Proxy'ler\",\n      \"sort\": \"Proxy'leri sırala\",\n      \"testDelay\": \"Gecikmeyi test et\",\n      \"empty\": \"Kullanılabilir proxy yok\",\n      \"activeProxy\": \"Aktif proxy\",\n      \"unknownIp\": \"Bilinmeyen IP\",\n      \"sortOptions\": {\n        \"unsorted\": \"Varsayılan\",\n        \"name\": \"Alfabetik\",\n        \"delay\": \"Gecikmeye göre\"\n      },\n      \"ipInfo\": {\n        \"address\": \"IP adresi\",\n        \"country\": \"Ülke\",\n        \"organization\": \"Kuruluş\"\n      },\n      \"delay\": {\n        \"result\": \"Gecikme: ${delay}ms\",\n        \"timeout\": \"Gecikme testi zaman aşımına uğradı\",\n        \"testing\": \"Gecikme: test ediliyor...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"Profiller\",\n      \"add\": \"Profil ekle\",\n      \"update\": \"Profili güncelle\",\n      \"viewAllProfiles\": \"Tüm profilleri görüntüle\",\n      \"activeProfileName\": \"Aktif profil adı: \\\"${name}\\\".\",\n      \"nonActiveProfileName\": \"Aktif profil olarak \\\"${name}\\\" seçin\",\n      \"freeSubNotFound\": \"Ücretsiz abonelik bulunamadı\",\n      \"freeSubNotFoundForRegion\": \"\\\"${region}\\\" bölgesi için ücretsiz abonelik bulunamadı\",\n      \"failedToLoad\": \"Yüklenemedi\",\n      \"updateSubscriptions\": \"Abonelikleri güncelle\",\n      \"share\": {\n        \"urlToClipboard\": \"URL'yi panoya kopyala\",\n        \"showUrlQr\": \"URL QR kodunu göster\",\n        \"jsonToClipboard\": \"JSON'u panoya kopyala\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"Profil başarıyla kaydedildi\"\n        },\n        \"invalidUrl\": \"Geçersiz URL\",\n        \"add\": {\n          \"failure\": \"Profil eklenemedi\"\n        },\n        \"update\": {\n          \"success\": \"Profil başarıyla güncellendi\",\n          \"successNamed\": \"\\\"${name}\\\" başarıyla güncellendi\",\n          \"failure\": \"Profil güncellenemedi\",\n          \"failureNamed\": \"\\\"${name}\\\" güncellenemedi\"\n        },\n        \"delete\": {\n          \"success\": \"Profil başarıyla silindi\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"Profil\",\n      \"lastUpdate\": \"Son güncelleme\",\n      \"form\": {\n        \"nameHint\": \"Profil adı\",\n        \"emptyName\": \"İsim gerekli\",\n        \"invalidUrl\": \"Geçersiz URL\",\n        \"urlHint\": \"Tam yapılandırma URL'si\",\n        \"disableAutoUpdate\": \"Otomatik güncellemeyi devre dışı bırak\",\n        \"autoUpdateInterval\": \"Otomatik güncelleme aralığı\",\n        \"loading\": \"Profil ekleniyor...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"Loglar\",\n      \"shareCoreLogs\": \"Çekirdek loglarını paylaş\",\n      \"shareAppLogs\": \"Uygulama loglarını paylaş\"\n    },\n    \"about\": {\n      \"title\": \"Hakkında\",\n      \"notAvailableMsg\": \"Zaten en son sürümü kullanıyorsunuz\",\n      \"checkForUpdate\": \"Güncellemeleri kontrol et\",\n      \"openWorkingDir\": \"Çalışma dizinini aç\",\n      \"sourceCode\": \"Kaynak kodu\",\n      \"telegramChannel\": \"Telegram kanalı\",\n      \"termsAndConditions\": \"Şartlar ve Koşullar\",\n      \"privacyPolicy\": \"Gizlilik Politikası\"\n    },\n    \"settings\": {\n      \"title\": \"Ayarlar\",\n      \"resetTunnel\": \"VPN profilini sıfırla\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"Seçenekleri panodan içe aktar\",\n          \"file\": \"Seçenekleri dosyadan içe aktar\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"Anonim seçenekleri panoya kopyala\",\n          \"anonymousToFile\": \"Anonim seçenekleri dosyaya aktar\",\n          \"allToClipboard\": \"Tüm seçenekleri panoya kopyala\",\n          \"allToFile\": \"Tüm seçenekleri dosyaya aktar\"\n        },\n        \"reset\": \"Seçenekleri sıfırla\"\n      },\n      \"general\": {\n        \"title\": \"Genel\",\n        \"locale\": \"Dil\",\n        \"themeMode\": \"Tema modu\",\n        \"themeModes\": {\n          \"system\": \"Sistem varsayılanı\",\n          \"dark\": \"Karanlık mod\",\n          \"light\": \"Açık mod\",\n          \"black\": \"Siyah mod\"\n        },\n        \"enableAnalytics\": \"Analizi etkinleştir\",\n        \"enableAnalyticsMsg\": \"Uygulamayı iyileştirmek için analiz ve kilitlenme raporları toplanmasına izin verin\",\n        \"autoIpCheck\": \"Bağlantı IP'sini otomatik kontrol et\",\n        \"dynamicNotification\": \"Hızı bildirimde göster\",\n        \"hapticFeedback\": \"Dokunsal geri bildirim\",\n        \"actionAtClosing\": \"Kapatma eylemi\",\n        \"autoStart\": \"Oturum açılışında başlat\",\n        \"silentStart\": \"Simge durumunda başlat\",\n        \"ignoreBatteryOptimizations\": \"Pil optimizasyonunu devre dışı bırak\",\n        \"ignoreBatteryOptimizationsMsg\": \"Optimum VPN performansı için kısıtlamaları kaldırın\",\n        \"memoryLimit\": \"Bellek limiti\",\n        \"memoryLimitMsg\": \"Bellek yetersizliği hataları veya sık uygulama çökmeleri yaşıyorsanız etkinleştirin\",\n        \"debugMode\": \"Hata ayıklama modu\",\n        \"debugModeMsg\": \"Bu değişikliği uygulamak için uygulamayı yeniden başlatın\",\n        \"logLevel\": \"Log seviyesi\",\n        \"connectionTestUrl\": \"Bağlantı testi URL'si\",\n        \"urlTestInterval\": \"URL testi aralığı\",\n        \"clashApiPort\": \"Clash API portu\",\n        \"useXrayCoreWhenPossible\": \"Mümkün olduğunda xray-core kullan\",\n        \"useXrayCoreWhenPossibleMsg\": \"Abonelik bağlantılarını ayrıştırırken xray-core kullanın. Bu seçeneği etkinleştirmek için bağlantıyı yeniden içe aktarmanız gerekir.\"\n      },\n      \"routing\": {\n        \"title\": \"Yönlendirme\",\n        \"perAppProxy\": {\n          \"title\": \"Uygulama bazlı proxy\",\n          \"hideSysApps\": \"Sistem uygulamalarını gizle\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Seçimi panodan içe aktar\",\n              \"file\": \"Seçimi dosyadan içe aktar\",\n              \"msg\": \"İçe aktarma mevcut seçimlerinizin üzerine yazacaktır. Devam etmek istediğinizden emin misiniz?\"\n            },\n            \"export\": {\n              \"clipboard\": \"Seçimi panoya kopyala\",\n              \"file\": \"Seçimi dosyaya aktar\"\n            },\n            \"shareToAll\": \"Herkesle paylaş\",\n            \"clearAllSelections\": \"Tüm seçimleri temizle\"\n          },\n          \"modes\": {\n            \"all\": \"Tümü\",\n            \"proxy\": \"Proxy\",\n            \"bypass\": \"Atla\",\n            \"allMsg\": \"Tüm uygulamaları proxy'le\",\n            \"proxyMsg\": \"Yalnızca seçili uygulamaları proxy'le\",\n            \"bypassMsg\": \"Seçili uygulamaları proxy'leme\"\n          },\n          \"autoSelection\": {\n            \"title\": \"Otomatik seçim\",\n            \"performNow\": \"Şimdi gerçekleştir\",\n            \"resetToDefault\": \"Varsayılana sıfırla\",\n            \"autoUpdateInterval\": \"Otomatik güncelleme aralığı\",\n            \"toast\": {\n              \"success\": \"Otomatik uygulama seçimi başarıyla tamamlandı\",\n              \"failure\": \"Otomatik seçim başarısız oldu\",\n              \"regionNotFound\": \"\\\"${region}\\\" bölgesi için otomatik seçim bulunamadı\",\n              \"alreadyInAuto\": \"Seçimleriniz zaten otomatik listede\"\n            },\n            \"dialog\": {\n              \"title\": \"Otomatik uygulama seçimi\",\n              \"msg\": \"Uygulama bazlı proxy için otomatik seçim özelliği, bölge \\\"${region}\\\" olarak değiştirildiği için devre dışı bırakıldı\"\n            }\n          }\n        },\n        \"region\": \"Bölge\",\n        \"regions\": {\n          \"ir\": \"İran (ir)\",\n          \"cn\": \"Çin (cn)\",\n          \"ru\": \"Rusya (ru)\",\n          \"af\": \"Afganistan (af)\",\n          \"id\": \"Endonezya (id)\",\n          \"tr\": \"Türkiye (tr)\",\n          \"br\": \"Brezilya (br)\",\n          \"other\": \"Diğer\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"Balancer stratejisi\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"Reklamları engelle\",\n        \"bypassLan\": \"LAN'ı atla\",\n        \"resolveDestination\": \"Hedefi çözümle\",\n        \"ipv6Route\": \"IPv6 rotası\",\n        \"ipv6Modes\": {\n          \"disable\": \"Devre dışı bırak\",\n          \"enable\": \"Etkinleştir\",\n          \"prefer\": \"Tercih et\",\n          \"only\": \"Sadece\"\n        },\n        \"routeRule\": {\n          \"title\": \"Yönlendirme kuralları\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"Kuralları panodan içe aktar\",\n              \"file\": \"Kuralları dosyadan içe aktar\"\n            },\n            \"export\": {\n              \"clipboard\": \"Kuralları panoya kopyala\",\n              \"file\": \"Kuralları dosyaya kaydet\"\n            },\n            \"reset\": \"Kuralları sıfırla\"\n          },\n          \"deleteRule\": \"Kuralı sil\",\n          \"createRule\": \"Yeni kural oluştur\",\n          \"rule\": {\n            \"title\": \"Kural\",\n            \"ruleChanged\": \"Kural değiştirildi\",\n            \"ruleChangedMsg\": \"Düzenlemelerinizi kaydetmek istiyor musunuz?\",\n            \"onlyTunMode\": \"Yalnızca TUN modunda kullanılabilir\",\n            \"notAvailabeInThisPlatform\": \"Bu platformda mevcut değil\",\n            \"canNotBeEmpty\": \"Boş olamaz\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"Geçerli \\\"URL\\\", örn.\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe veya google chrome veya chrome\",\n            \"validProcessName\": \"Geçerli \\\"İşlem Adı\\\", örn.\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"Geçerli \\\"İşlem Yolu\\\", örn.\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 veya 1-65000\",\n            \"validPortRange\": \"Geçerli \\\"Port\\\" veya \\\"Port Aralığı\\\", örn.\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 veya 10.0.0.0/24\",\n            \"validIpCidr\": \"Geçerli IP CIDR, örn.\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com veya dl.google.com\",\n            \"validDomain\": \"Geçerli \\\"Alan Adı\\\", örn.\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com veya .tr\",\n            \"validDomainSuffix\": \"Geçerli \\\"Alan Adı Son Eki\\\", örn.\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"İsim\",\n              \"outbound\": \"Eşleşirse giden\",\n              \"rule_set\": \"Kural seti URL'si\",\n              \"package_name\": \"Paket adları\",\n              \"process_name\": \"İşlem adları\",\n              \"process_path\": \"İşlem yolları\",\n              \"network\": \"Ağlar\",\n              \"port_range\": \"Hedef portlar\",\n              \"source_port_range\": \"Kaynak portlar\",\n              \"protocol\": \"Protokol\",\n              \"ip_cidr\": \"Hedef IP CIDR\",\n              \"source_ip_cidr\": \"Kaynak IP CIDR\",\n              \"domain\": \"Alan adı\",\n              \"domain_suffixe\": \"Alan adı son eki\",\n              \"domain_keyword\": \"Alan adı anahtar kelimesi\",\n              \"domain_regex\": \"Alan adı regex\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"Proxy\",\n              \"direct\": \"Doğrudan\",\n              \"direct_with_fragment\": \"Doğrudan (fragment ile)\",\n              \"block\": \"Engelle\"\n            },\n            \"network(map)\": {\n              \"all\": \"Tümü\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"Tümü\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"Yeni değer ekle\",\n            \"update\": \"Değeri güncelle\",\n            \"clearList\": \"Listeyi temizle\",\n            \"clearListMsg\": \"Tüm öğeler silindi\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"Android uygulamaları\",\n            \"showSystemApps\": \"Sistem uygulamalarını göster\",\n            \"hideSystemApps\": \"Sistem uygulamalarını gizle\",\n            \"clearSelection\": \"Seçimi temizle\",\n            \"uninstalled\": \"Kaldırıldı\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"Uzak DNS\",\n        \"remoteDnsDomainStrategy\": \"Uzak DNS alan adı stratejisi\",\n        \"directDns\": \"Giden sunucu çözümleyicisi (doğrudan)\",\n        \"directDnsDomainStrategy\": \"Giden alan adı stratejisi\",\n        \"enableDnsRouting\": \"DNS yönlendirmeyi etkinleştir\",\n        \"enableFakeDns\": \"Sahte DNS'i etkinleştir\",\n        \"domainStrategy\": {\n          \"auto\": \"Otomatik\",\n          \"preferIpv6\": \"IPv6 tercih et\",\n          \"preferIpv4\": \"IPv4 tercih et\",\n          \"ipv4Only\": \"Sadece IPv4\",\n          \"ipv6Only\": \"Sadece IPv6\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"Gelen\",\n        \"serviceMode\": \"Servis modu\",\n        \"serviceModes\": {\n          \"proxy\": \"Yalnızca proxy servisi\",\n          \"systemProxy\": \"Sistem proxy'sini ayarla\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"VPN servisi\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"Proxy\",\n          \"systemProxy\": \"Sistem proxy'si\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"VPN servisi\"\n        },\n        \"strictRoute\": \"Katı yönlendirme\",\n        \"tunImplementation\": \"TUN uygulaması\",\n        \"tunImplementations\": {\n          \"mixed\": \"Karışık\",\n          \"system\": \"Sistem\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"Karışık port\",\n        \"tproxyPort\": \"Şeffaf proxy portu\",\n        \"directPort\": \"Direct portu\",\n        \"redirectPort\": \"Yönlendirme portu\",\n        \"allowConnectionFromLan\": \"VPN'i yerel ağda paylaş\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"TLS hileleri\",\n        \"enable\": \"Fragment'ı etkinleştir\",\n        \"packets\": \"Fragmentation Paketleri\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"Fragment boyutu\",\n        \"sleep\": \"Fragment gecikmesi\",\n        \"mixedSniCase\": {\n          \"enable\": \"Karışık SNI harf durumunu etkinleştir\"\n        },\n        \"padding\": {\n          \"enable\": \"Dolguyu etkinleştir\",\n          \"size\": \"Dolgu boyutu\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"WARP'ı etkinleştir\",\n        \"generateConfig\": \"WARP yapılandırması oluştur\",\n        \"configGenerated\": \"WARP yapılandırması oluşturuldu\",\n        \"missingConfig\": \"WARP yapılandırması eksik\",\n        \"detourMode\": \"Yönlendirme modu\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"Proxy'leri WARP üzerinden yönlendir\",\n          \"warpOverProxy\": \"WARP'ı proxy'ler üzerinden yönlendir\",\n          \"proxyOverWarpExplain\": \"Proxy'lerin engelini WARP ile kaldır\",\n          \"warpOverProxyExplain\": \"WARP ile ekstra güvenlik\"\n        },\n        \"licenseKey\": \"Lisans anahtarı\",\n        \"cleanIp\": \"Temiz IP\",\n        \"port\": \"Port\",\n        \"noise\": {\n          \"count\": \"Gürültü sayısı\",\n          \"mode\": \"Gürültü modu\",\n          \"size\": \"Gürültü boyutu\",\n          \"delay\": \"Gürültü gecikmesi\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"Bağlantı\",\n      \"traffic\": \"Trafik\",\n      \"trafficLive\": \"Canlı trafik\",\n      \"trafficTotal\": \"Toplam trafik\",\n      \"uplink\": \"Yükleme\",\n      \"downlink\": \"İndirme\",\n      \"speed\": \"Hız\",\n      \"totalTransferred\": \"Toplam aktarılan\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"Yükleme\",\n      \"download\": \"İndirme\",\n      \"total\": \"Toplam trafik\",\n      \"expireDate\": \"Bitiş tarihi\",\n      \"expired\": \"Süresi doldu\",\n      \"noTraffic\": \"Kota doldu\",\n      \"remainingTime\": \"Kalan süre\",\n      \"remainingDuration\": \"kalan ${duration} gün\",\n      \"remainingDurationNew\": \"${duration} gün\",\n      \"remainingTrafficSemanticLabel\": \"${consumed} / ${total} trafik kullanıldı\",\n      \"remainingTraffic\": \"Kalan trafik\",\n      \"remainingUsage\": \"Kalan\",\n      \"profileSite\": \"Sağlayıcı\",\n      \"profileSupport\": \"Destek\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"Sıralama ölçütü\",\n      \"sort\": {\n        \"name\": \"Alfabetik\",\n        \"lastUpdate\": \"Son güncelleme\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"Cloudflare WARP onayı\",\n      \"description(rich)\": \"Cloudflare WARP ücretsiz bir WireGuard VPN sağlayıcısıdır. Bu seçeneği etkinleştirerek Cloudflare WARP'ın ${tos(Hizmet Şartları)}'nı ve ${privacy(Gizlilik Politikası)}'nı kabul etmiş olursunuz.\"\n    },\n    \"newVersion\": {\n      \"title\": \"Güncelleme mevcut\",\n      \"msg\": \"@:common.appTitle'ın yeni bir sürümü mevcut. Şimdi güncellemek ister misiniz?\",\n      \"currentVersion\": \"Mevcut sürüm: \",\n      \"newVersion\": \"Yeni sürüm: \",\n      \"updateNow\": \"Şimdi güncelle\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"Bu işlem tüm yapılandırma seçeneklerini verilen değerlerle yeniden yazacaktır. Emin misiniz?\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"Profili sil\",\n          \"msg\": \"Bu profili kalıcı olarak silmek istediğinizden emin misiniz?\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"Otomatik seçimi iyileştirme\",\n          \"msg\": \"Seçili uygulamaları paylaşarak \\\"otomatik seçim\\\" listesini tamamlamaya yardımcı olursunuz\"\n        },\n        \"import\": {\n          \"msg\": \"Bu işlem mevcut tüm uygulama bazlı proxy seçimlerinizi değiştirecektir. Devam etmek istediğinizden emin misiniz?\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"Kuralı sil\",\n          \"msg\": \"\\\"$rulename\\\" kuralını silmek istediğinizden emin misiniz?\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"Deneysel özellikler kullanılıyor\",\n      \"msg\": \"Bağlantı kalitesini etkileyebilecek ve beklenmedik hatalara neden olabilecek bazı deneysel özellikleri etkinleştirdiniz. Bu seçenekleri istediğiniz zaman yapılandırma sayfasından değiştirebilir veya sıfırlayabilirsiniz.\",\n      \"disable\": \"Tekrar gösterme\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"Bir profil seçin\",\n      \"msg\": \"VPN bağlantı ayrıntılarınızı içeren bir bağlantı profili ekleyerek başlayalım.\\n\\nHenüz bir VPN sunucunuz yok mu? Endişelenmeyin, hızlı ve ücretsiz bir şekilde kurmak için aşağıdaki eğitimi takip edin.\",\n      \"helpBtn\": {\n        \"label\": \"Nasıl yapıldığını göster\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"Dış bağlantı uyarısı\",\n      \"youAreAboutToVisit\": \"Şu adresi ziyaret etmek üzeresiniz:\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"Bu web sitesi güvenilir listemizde değil. Lütfen dikkatli devam edin.\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"Tam etiket:\",\n      \"type\": \"Tür:\",\n      \"testTime\": \"Test zamanı:\",\n      \"testDelay\": \"Test gecikmesi:\",\n      \"isSelected\": \"Seçili:\",\n      \"isGroup\": \"Grup\",\n      \"isSecure\": \"Güvenli:\",\n      \"port\": \"Port:\",\n      \"host\": \"Sunucu:\",\n      \"ip\": \"IP:\",\n      \"countryCode\": \"Ülke kodu:\",\n      \"region\": \"Bölge:\",\n      \"city\": \"Şehir:\",\n      \"asn\": \"ASN:\",\n      \"organization\": \"Kuruluş:\",\n      \"location\": \"Konum:\",\n      \"postalCode\": \"Posta kodu:\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"Her seferinde sor\",\n      \"alertMessage\": \"Uygulama gizlensin mi, kapatılsın mı?\",\n      \"remember\": \"Seçimimi hatırla\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"Bağlanmak için dokunun\",\n    \"connect\": \"Bağlan\",\n    \"connecting\": \"Bağlanıyor...\",\n    \"connected\": \"Bağlı\",\n    \"disconnect\": \"Bağlantıyı kes\",\n    \"disconnecting\": \"Bağlantı kesiliyor...\",\n    \"reconnect\": \"Yeniden bağlan\",\n    \"reconnectMsg\": \"Değişiklikleri uygulamak için yeniden bağlanılıyor...\",\n    \"secure\": \"WARP ile güvende\"\n  },\n  \"errors\": {\n    \"unexpected\": \"Beklenmeyen hata\",\n    \"connection\": {\n      \"unexpected\": \"Beklenmeyen bağlantı hatası\",\n      \"timeout\": \"Bağlantı zaman aşımına uğradı\",\n      \"badResponse\": \"Hatalı yanıt\",\n      \"connectionError\": \"Bağlantı hatası\",\n      \"badCertificate\": \"Geçersiz sertifika\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"Beklenmeyen hata\",\n      \"notFound\": \"Profil bulunamadı\",\n      \"invalidConfig\": \"Geçersiz yapılandırmalar\",\n      \"invalidUrl\": \"Geçersiz URL\",\n      \"canceledByUser\": \"Kullanıcı tarafından iptal edildi\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"Beklenmeyen hata\",\n      \"missingVpnPermission\": \"VPN izni eksik\",\n      \"missingNotificationPermission\": \"Bildirim izni eksik\",\n      \"core\": \"Çekirdek hatası\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"Servis çalışmıyor\",\n      \"missingPrivilege\": \"Eksik yetki\",\n      \"missingPrivilegeMsg\": \"VPN modu yönetici yetkisi gerektirir. Lütfen uygulamayı yönetici olarak yeniden başlatın veya servis modunu değiştirin.\",\n      \"invalidConfigOptions\": \"Geçersiz yapılandırma seçenekleri\",\n      \"invalidConfig\": \"Geçersiz yapılandırma\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"WARP lisansı eksik\",\n      \"missingLicenseMsg\": \"Seçili profil WARP özelliğini kullanıyor. Bu özelliği kullanmak için WARP lisansını kabul etmeniz gerekir.\"\n    }\n  }\n}"
  },
  {
    "path": "assets/translations/zh-CN.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"Hiddify\",\n    \"start\": \"开始\",\n    \"version\": \"版本\",\n    \"ok\": \"确定\",\n    \"cancel\": \"取消\",\n    \"kContinue\": \"继续\",\n    \"showMore\": \"显示更多\",\n    \"showLess\": \"显示更少\",\n    \"filter\": \"筛选\",\n    \"all\": \"全部\",\n    \"pause\": \"暂停\",\n    \"resume\": \"恢复\",\n    \"clear\": \"清除\",\n    \"close\": \"关闭\",\n    \"auto\": \"自动\",\n    \"manually\": \"手动\",\n    \"name\": \"名称\",\n    \"url\": \"URL\",\n    \"add\": \"添加\",\n    \"clipboard\": \"剪贴板\",\n    \"addToClipboard\": \"添加到剪贴板\",\n    \"scanQr\": \"扫描二维码\",\n    \"free\": \"免费\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Fragment\",\n    \"help\": \"帮助\",\n    \"save\": \"保存\",\n    \"update\": \"更新\",\n    \"share\": \"分享\",\n    \"edit\": \"编辑\",\n    \"delete\": \"删除\",\n    \"discard\": \"放弃\",\n    \"import\": \"导入\",\n    \"export\": \"导出\",\n    \"later\": \"稍后\",\n    \"ignore\": \"忽略\",\n    \"quit\": \"退出\",\n    \"notSet\": \"未设置\",\n    \"hide\": \"隐藏\",\n    \"exit\": \"退出\",\n    \"reset\": \"重置\",\n    \"done\": \"完成\",\n    \"search\": \"搜索\",\n    \"decline\": \"拒绝\",\n    \"agree\": \"同意\",\n    \"empty\": \"空\",\n    \"unknown\": \"未知\",\n    \"hidden\": \"隐藏\",\n    \"timeout\": \"超时\",\n    \"sort\": \"排序\",\n    \"dashboard\": \"仪表盘\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"$n 天\",\n        \"other\": \"$n 天\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"$n 小时\",\n        \"other\": \"$n 小时\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"权限被拒绝\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"已成功添加到剪贴板\",\n          \"failure\": \"复制到剪贴板失败\",\n          \"contentTooLarge\": \"内容过大，请使用导出文件\"\n        },\n        \"file\": {\n          \"success\": \"JSON 文件创建成功\",\n          \"failure\": \"创建文件失败\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"确认导入\",\n        \"success\": \"导入成功\",\n        \"failure\": \"导入失败\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"畅享无限制网络的所需一切\",\n    \"termsAndPolicyCaution(rich)\": \"继续即表示您同意 ${tap(@:pages.about.termsAndConditions)}\",\n    \"info(rich)\": \"由 Hiddify 用 ❤️ 制作 - ${tap_source(开源)} (${tap_license(许可证)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"主页\",\n      \"quickSettings\": \"快速设置\"\n    },\n    \"proxies\": {\n      \"title\": \"代理\",\n      \"sort\": \"排序代理\",\n      \"testDelay\": \"测试延迟\",\n      \"empty\": \"无可用代理\",\n      \"activeProxy\": \"当前代理\",\n      \"unknownIp\": \"未知 IP\",\n      \"sortOptions\": {\n        \"unsorted\": \"默认\",\n        \"name\": \"按名称\",\n        \"delay\": \"按延迟\"\n      },\n      \"ipInfo\": {\n        \"address\": \"IP 地址\",\n        \"country\": \"国家\",\n        \"organization\": \"组织\"\n      },\n      \"delay\": {\n        \"result\": \"延迟：${delay}毫秒\",\n        \"timeout\": \"延迟测试超时\",\n        \"testing\": \"延迟：测试中...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"配置文件\",\n      \"add\": \"添加配置文件\",\n      \"update\": \"更新配置文件\",\n      \"viewAllProfiles\": \"查看所有配置文件\",\n      \"activeProfileName\": \"当前配置文件：\\\"${name}\\\"\",\n      \"nonActiveProfileName\": \"选择 \\\"${name}\\\" 作为当前配置文件\",\n      \"freeSubNotFound\": \"未找到免费订阅\",\n      \"freeSubNotFoundForRegion\": \"未找到 \\\"${region}\\\" 地区的免费订阅\",\n      \"failedToLoad\": \"加载失败\",\n      \"updateSubscriptions\": \"更新订阅\",\n      \"share\": {\n        \"urlToClipboard\": \"URL 到剪贴板\",\n        \"showUrlQr\": \"显示 URL 二维码\",\n        \"jsonToClipboard\": \"JSON 到剪贴板\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"配置文件保存成功\"\n        },\n        \"invalidUrl\": \"无效的 URL\",\n        \"add\": {\n          \"failure\": \"添加配置文件失败\"\n        },\n        \"update\": {\n          \"success\": \"配置文件更新成功\",\n          \"successNamed\": \"\\\"${name}\\\" 更新成功\",\n          \"failure\": \"更新配置文件失败\",\n          \"failureNamed\": \"更新 \\\"${name}\\\" 失败\"\n        },\n        \"delete\": {\n          \"success\": \"配置文件删除成功\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"配置文件\",\n      \"lastUpdate\": \"最后更新\",\n      \"form\": {\n        \"nameHint\": \"配置文件名称\",\n        \"emptyName\": \"名称为必填项\",\n        \"invalidUrl\": \"无效的 URL\",\n        \"urlHint\": \"完整的配置 URL\",\n        \"disableAutoUpdate\": \"禁用自动更新\",\n        \"autoUpdateInterval\": \"自动更新间隔\",\n        \"loading\": \"正在添加配置文件...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"日志\",\n      \"shareCoreLogs\": \"分享核心日志\",\n      \"shareAppLogs\": \"分享应用日志\"\n    },\n    \"about\": {\n      \"title\": \"关于\",\n      \"notAvailableMsg\": \"已是最新版本\",\n      \"checkForUpdate\": \"检查更新\",\n      \"openWorkingDir\": \"打开工作目录\",\n      \"sourceCode\": \"源代码\",\n      \"telegramChannel\": \"Telegram 频道\",\n      \"termsAndConditions\": \"条款与条件\",\n      \"privacyPolicy\": \"隐私政策\"\n    },\n    \"settings\": {\n      \"title\": \"设置\",\n      \"resetTunnel\": \"重置 VPN 配置文件\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"从剪贴板导入选项\",\n          \"file\": \"从文件导入选项\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"复制匿名选项到剪贴板\",\n          \"anonymousToFile\": \"导出匿名选项到文件\",\n          \"allToClipboard\": \"复制所有选项到剪贴板\",\n          \"allToFile\": \"导出所有选项到文件\"\n        },\n        \"reset\": \"重置选项\"\n      },\n      \"general\": {\n        \"title\": \"通用\",\n        \"locale\": \"语言\",\n        \"themeMode\": \"主题模式\",\n        \"themeModes\": {\n          \"system\": \"跟随系统\",\n          \"dark\": \"深色模式\",\n          \"light\": \"浅色模式\",\n          \"black\": \"纯黑模式\"\n        },\n        \"enableAnalytics\": \"启用分析\",\n        \"enableAnalyticsMsg\": \"允许收集分析数据和发送崩溃报告以改进应用\",\n        \"autoIpCheck\": \"自动检查连接 IP\",\n        \"dynamicNotification\": \"在通知中显示速度\",\n        \"hapticFeedback\": \"触觉反馈\",\n        \"actionAtClosing\": \"关闭时操作\",\n        \"autoStart\": \"开机自启\",\n        \"silentStart\": \"静默启动\",\n        \"ignoreBatteryOptimizations\": \"忽略电池优化\",\n        \"ignoreBatteryOptimizationsMsg\": \"移除限制以获得最佳 VPN 性能\",\n        \"memoryLimit\": \"内存限制\",\n        \"memoryLimitMsg\": \"如果您遇到内存不足错误或应用频繁崩溃，请启用此选项\",\n        \"debugMode\": \"调试模式\",\n        \"debugModeMsg\": \"重启应用以应用此更改\",\n        \"logLevel\": \"日志级别\",\n        \"connectionTestUrl\": \"连接测试 URL\",\n        \"urlTestInterval\": \"URL 测试间隔\",\n        \"clashApiPort\": \"Clash API 端口\",\n        \"useXrayCoreWhenPossible\": \"尽可能使用 xray-core\",\n        \"useXrayCoreWhenPossibleMsg\": \"解析订阅链接时使用 xray-core。您需要重新导入订阅链接才能启用此选项\"\n      },\n      \"routing\": {\n        \"title\": \"路由\",\n        \"perAppProxy\": {\n          \"title\": \"分应用代理\",\n          \"hideSysApps\": \"隐藏系统应用\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"从剪贴板导入选择\",\n              \"file\": \"从文件导入选择\",\n              \"msg\": \"导入将替换您当前的选择。确定要继续吗？\"\n            },\n            \"export\": {\n              \"clipboard\": \"复制选择到剪贴板\",\n              \"file\": \"导出选择到文件\"\n            },\n            \"shareToAll\": \"分享给所有人\",\n            \"clearAllSelections\": \"清除所有选择\"\n          },\n          \"modes\": {\n            \"all\": \"全部\",\n            \"proxy\": \"代理\",\n            \"bypass\": \"绕过\",\n            \"allMsg\": \"代理所有应用\",\n            \"proxyMsg\": \"仅代理选定应用\",\n            \"bypassMsg\": \"不代理选定应用\"\n          },\n          \"autoSelection\": {\n            \"title\": \"自动选择\",\n            \"performNow\": \"立即执行\",\n            \"resetToDefault\": \"重置为默认\",\n            \"autoUpdateInterval\": \"自动更新间隔\",\n            \"toast\": {\n              \"success\": \"自动选择应用成功完成\",\n              \"failure\": \"自动选择失败\",\n              \"regionNotFound\": \"未找到 \\\"${region}\\\" 地区的自动选择\",\n              \"alreadyInAuto\": \"您的选择已在自动列表中\"\n            },\n            \"dialog\": {\n              \"title\": \"自动选择应用\",\n              \"msg\": \"由于地区更改为 \\\"${region}\\\"，分应用代理的自动选择功能已被禁用\"\n            }\n          }\n        },\n        \"region\": \"地区\",\n        \"regions\": {\n          \"ir\": \"伊朗 (ir)\",\n          \"cn\": \"中国 (cn)\",\n          \"ru\": \"俄罗斯 (ru)\",\n          \"af\": \"阿富汗 (af)\",\n          \"id\": \"印度尼西亚 (id)\",\n          \"tr\": \"土耳其 (tr)\",\n          \"br\": \"巴西 (br)\",\n          \"other\": \"其他\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"Balancer 策略\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"拦截广告\",\n        \"bypassLan\": \"绕过局域网\",\n        \"resolveDestination\": \"解析目的地\",\n        \"ipv6Route\": \"IPv6 路由\",\n        \"ipv6Modes\": {\n          \"disable\": \"禁用\",\n          \"enable\": \"启用\",\n          \"prefer\": \"首选\",\n          \"only\": \"仅\"\n        },\n        \"routeRule\": {\n          \"title\": \"路由规则\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"从剪贴板导入规则\",\n              \"file\": \"从文件导入规则\"\n            },\n            \"export\": {\n              \"clipboard\": \"复制规则到剪贴板\",\n              \"file\": \"保存规则到文件\"\n            },\n            \"reset\": \"重置规则\"\n          },\n          \"deleteRule\": \"删除规则\",\n          \"createRule\": \"创建新规则\",\n          \"rule\": {\n            \"title\": \"规则\",\n            \"ruleChanged\": \"规则已更改\",\n            \"ruleChangedMsg\": \"您想保存您的编辑吗？\",\n            \"onlyTunMode\": \"仅在 TUN 模式下可用\",\n            \"notAvailabeInThisPlatform\": \"在此平台上不可用\",\n            \"canNotBeEmpty\": \"不能为空\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"有效的 \\\"URL\\\"，例如\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe 或 google chrome 或 chrome\",\n            \"validProcessName\": \"有效的 \\\"进程名\\\"，例如\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"有效的 \\\"进程路径\\\"，例如\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 或 1-65000\",\n            \"validPortRange\": \"有效的 \\\"端口\\\" 或 \\\"端口范围\\\"，例如\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 或 10.0.0.0/24\",\n            \"validIpCidr\": \"有效的 IP CIDR，例如\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com 或 dl.google.com\",\n            \"validDomain\": \"有效的 \\\"域名\\\"，例如\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com 或 .cn\",\n            \"validDomainSuffix\": \"有效的 \\\"域名后缀\\\"，例如\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"名称\",\n              \"outbound\": \"匹配时出站\",\n              \"rule_set\": \"规则集 URL\",\n              \"package_name\": \"包名\",\n              \"process_name\": \"进程名\",\n              \"process_path\": \"进程路径\",\n              \"network\": \"网络\",\n              \"port_range\": \"目标端口\",\n              \"source_port_range\": \"源端口\",\n              \"protocol\": \"协议\",\n              \"ip_cidr\": \"目标 IP CIDR\",\n              \"source_ip_cidr\": \"源 IP CIDR\",\n              \"domain\": \"域名\",\n              \"domain_suffixe\": \"域名后缀\",\n              \"domain_keyword\": \"域名关键词\",\n              \"domain_regex\": \"域名正则表达式\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"代理\",\n              \"direct\": \"直连\",\n              \"direct_with_fragment\": \"直连并分片\",\n              \"block\": \"拦截\"\n            },\n            \"network(map)\": {\n              \"all\": \"全部\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"全部\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"添加新值\",\n            \"update\": \"更新值\",\n            \"clearList\": \"清空列表\",\n            \"clearListMsg\": \"所有项目已删除\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"安卓应用\",\n            \"showSystemApps\": \"显示系统应用\",\n            \"hideSystemApps\": \"隐藏系统应用\",\n            \"clearSelection\": \"清除选择\",\n            \"uninstalled\": \"已卸载\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"远程 DNS\",\n        \"remoteDnsDomainStrategy\": \"远程 DNS 域名策略\",\n        \"directDns\": \"出站服务器解析器（直连）\",\n        \"directDnsDomainStrategy\": \"出站域名策略\",\n        \"enableDnsRouting\": \"启用 DNS 路由\",\n        \"enableFakeDns\": \"启用伪造 DNS\",\n        \"domainStrategy\": {\n          \"auto\": \"自动\",\n          \"preferIpv6\": \"偏好 IPv6\",\n          \"preferIpv4\": \"偏好 IPv4\",\n          \"ipv4Only\": \"仅 IPv4\",\n          \"ipv6Only\": \"仅 IPv6\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"入站\",\n        \"serviceMode\": \"服务模式\",\n        \"serviceModes\": {\n          \"proxy\": \"仅代理服务\",\n          \"systemProxy\": \"设置系统代理\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"VPN 服务\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"代理\",\n          \"systemProxy\": \"系统代理\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"VPN 服务\"\n        },\n        \"strictRoute\": \"严格路由\",\n        \"tunImplementation\": \"TUN 实现\",\n        \"tunImplementations\": {\n          \"mixed\": \"混合\",\n          \"system\": \"系统\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"混合端口\",\n        \"tproxyPort\": \"透明代理端口\",\n        \"directPort\": \"本地 Direct 端口\",\n        \"redirectPort\": \"重定向端口\",\n        \"allowConnectionFromLan\": \"允许来自局域网的连接\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"TLS 技巧\",\n        \"enable\": \"启用分片\",\n        \"packets\": \"分片数据包\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"分片大小\",\n        \"sleep\": \"分片延迟\",\n        \"mixedSniCase\": {\n          \"enable\": \"启用混合大小写 SNI\"\n        },\n        \"padding\": {\n          \"enable\": \"启用填充\",\n          \"size\": \"填充大小\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"启用 WARP\",\n        \"generateConfig\": \"生成 WARP 配置\",\n        \"configGenerated\": \"WARP 配置已生成\",\n        \"missingConfig\": \"WARP 配置缺失\",\n        \"detourMode\": \"WARP 路由模式\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"通过 WARP 路由代理\",\n          \"warpOverProxy\": \"通过代理路由 WARP\",\n          \"proxyOverWarpExplain\": \"通过 WARP 解锁代理\",\n          \"warpOverProxyExplain\": \"通过 WARP 增强安全性\"\n        },\n        \"licenseKey\": \"许可证密钥\",\n        \"cleanIp\": \"优选 IP\",\n        \"port\": \"端口\",\n        \"noise\": {\n          \"count\": \"噪声数量\",\n          \"mode\": \"噪声模式\",\n          \"size\": \"噪声大小\",\n          \"delay\": \"噪声延迟\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"连接\",\n      \"traffic\": \"流量\",\n      \"trafficLive\": \"实时流量\",\n      \"trafficTotal\": \"总流量\",\n      \"uplink\": \"上传\",\n      \"downlink\": \"下载\",\n      \"speed\": \"速度\",\n      \"totalTransferred\": \"总传输量\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"上传\",\n      \"download\": \"下载\",\n      \"total\": \"总流量\",\n      \"expireDate\": \"到期日期\",\n      \"expired\": \"已过期\",\n      \"noTraffic\": \"流量已用尽\",\n      \"remainingTime\": \"剩余时间\",\n      \"remainingDuration\": \"剩余 ${duration} 天\",\n      \"remainingDurationNew\": \"${duration} 天\",\n      \"remainingTrafficSemanticLabel\": \"已使用 ${consumed} / ${total} 流量\",\n      \"remainingTraffic\": \"剩余流量\",\n      \"remainingUsage\": \"剩余\",\n      \"profileSite\": \"提供商\",\n      \"profileSupport\": \"支持\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"排序方式\",\n      \"sort\": {\n        \"name\": \"按字母顺序\",\n        \"lastUpdate\": \"最近更新\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"Cloudflare WARP 同意书\",\n      \"description(rich)\": \"Cloudflare WARP 是一个免费的 WireGuard VPN 提供商。启用此选项即表示您同意 Cloudflare WARP 的 ${tos(服务条款)} 和 ${privacy(隐私政策)}。\"\n    },\n    \"newVersion\": {\n      \"title\": \"有可用更新\",\n      \"msg\": \"@:common.appTitle 的新版本已发布。您想现在更新吗？\",\n      \"currentVersion\": \"当前版本：\",\n      \"newVersion\": \"新版本：\",\n      \"updateNow\": \"立即更新\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"这将用提供的值覆盖所有配置选项。您确定吗？\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"删除配置文件\",\n          \"msg\": \"您确定要永久删除此配置文件吗？\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"改进自动选择\",\n          \"msg\": \"通过分享您选择的应用，可以帮助完善“自动选择”列表\"\n        },\n        \"import\": {\n          \"msg\": \"这将替换您当前所有的分应用代理选择。您确定要继续吗？\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"删除规则\",\n          \"msg\": \"您确定要删除规则 \\\"$rulename\\\" 吗？\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"正在使用实验性功能\",\n      \"msg\": \"您已启用了一些实验性功能，这可能会影响连接质量并导致意外错误。您可以随时在配置选项页面更改或重置这些选项。\",\n      \"disable\": \"不再显示\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"选择一个配置文件\",\n      \"msg\": \"让我们从添加一个包含您 VPN 连接详细信息的配置文件开始。\\n\\n还没有 VPN 服务器？别担心，按照下面的教程，您可以快速免费地设置一个。\",\n      \"helpBtn\": {\n        \"label\": \"告诉我如何操作\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"外部链接警告\",\n      \"youAreAboutToVisit\": \"您即将访问：\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"此网站不在我们的信任列表中。请谨慎操作。\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"完整标签：\",\n      \"type\": \"类型：\",\n      \"testTime\": \"测试时间：\",\n      \"testDelay\": \"测试延迟：\",\n      \"isSelected\": \"已选择：\",\n      \"isGroup\": \"是组\",\n      \"isSecure\": \"安全：\",\n      \"port\": \"端口：\",\n      \"host\": \"主机：\",\n      \"ip\": \"IP：\",\n      \"countryCode\": \"国家代码：\",\n      \"region\": \"地区：\",\n      \"city\": \"城市：\",\n      \"asn\": \"ASN：\",\n      \"organization\": \"组织：\",\n      \"location\": \"位置：\",\n      \"postalCode\": \"邮政编码：\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"每次询问\",\n      \"alertMessage\": \"隐藏还是退出应用程序？\",\n      \"remember\": \"记住我的选择\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"点击连接\",\n    \"connect\": \"连接\",\n    \"connecting\": \"连接中...\",\n    \"connected\": \"已连接\",\n    \"disconnect\": \"断开连接\",\n    \"disconnecting\": \"断开连接中...\",\n    \"reconnect\": \"重新连接\",\n    \"reconnectMsg\": \"正在重新连接以应用更改...\",\n    \"secure\": \"由 WARP 保护\"\n  },\n  \"errors\": {\n    \"unexpected\": \"意外错误\",\n    \"connection\": {\n      \"unexpected\": \"意外连接错误\",\n      \"timeout\": \"连接超时\",\n      \"badResponse\": \"响应错误\",\n      \"connectionError\": \"连接错误\",\n      \"badCertificate\": \"证书无效\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"意外错误\",\n      \"notFound\": \"未找到配置文件\",\n      \"invalidConfig\": \"配置无效\",\n      \"invalidUrl\": \"URL 无效\",\n      \"canceledByUser\": \"用户已取消\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"意外失败\",\n      \"missingVpnPermission\": \"缺少 VPN 权限\",\n      \"missingNotificationPermission\": \"缺少通知权限\",\n      \"core\": \"核心错误\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"服务未运行\",\n      \"missingPrivilege\": \"缺少权限\",\n      \"missingPrivilegeMsg\": \"VPN 模式需要管理员权限。请以管理员身份重新启动应用，或更改服务模式。\",\n      \"invalidConfigOptions\": \"配置选项无效\",\n      \"invalidConfig\": \"配置无效\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"WARP 许可证缺失\",\n      \"missingLicenseMsg\": \"所选配置文件使用 WARP 功能；要使用此功能，必须同意 WARP 许可证。\"\n    }\n  }\n}"
  },
  {
    "path": "assets/translations/zh-TW.i18n.json",
    "content": "{\n  \"common\": {\n    \"appTitle\": \"Hiddify\",\n    \"start\": \"開始\",\n    \"version\": \"版本\",\n    \"ok\": \"確定\",\n    \"cancel\": \"取消\",\n    \"kContinue\": \"繼續\",\n    \"showMore\": \"顯示更多\",\n    \"showLess\": \"顯示較少\",\n    \"filter\": \"篩選\",\n    \"all\": \"全部\",\n    \"pause\": \"暫停\",\n    \"resume\": \"恢復\",\n    \"clear\": \"清除\",\n    \"close\": \"關閉\",\n    \"auto\": \"自動\",\n    \"manually\": \"手動\",\n    \"name\": \"名稱\",\n    \"url\": \"URL\",\n    \"add\": \"新增\",\n    \"clipboard\": \"剪貼簿\",\n    \"addToClipboard\": \"新增至剪貼簿\",\n    \"scanQr\": \"掃描 QR Code\",\n    \"free\": \"免費\",\n    \"warp\": \"WARP\",\n    \"fragment\": \"Fragment\",\n    \"help\": \"說明\",\n    \"save\": \"儲存\",\n    \"update\": \"更新\",\n    \"share\": \"分享\",\n    \"edit\": \"編輯\",\n    \"delete\": \"刪除\",\n    \"discard\": \"捨棄\",\n    \"import\": \"匯入\",\n    \"export\": \"匯出\",\n    \"later\": \"稍後\",\n    \"ignore\": \"忽略\",\n    \"quit\": \"退出\",\n    \"notSet\": \"未設定\",\n    \"hide\": \"隱藏\",\n    \"exit\": \"退出\",\n    \"reset\": \"重設\",\n    \"done\": \"完成\",\n    \"search\": \"搜尋\",\n    \"decline\": \"拒絕\",\n    \"agree\": \"同意\",\n    \"empty\": \"空\",\n    \"unknown\": \"未知\",\n    \"hidden\": \"隱藏\",\n    \"timeout\": \"超時\",\n    \"sort\": \"排序\",\n    \"dashboard\": \"儀表板\",\n    \"interval\": {\n      \"day\": {\n        \"zero\": \"\",\n        \"one\": \"$n 天\",\n        \"other\": \"$n 天\"\n      },\n      \"hour\": {\n        \"zero\": \"\",\n        \"one\": \"$n 小時\",\n        \"other\": \"$n 小時\"\n      }\n    },\n    \"msg\": {\n      \"permission\": {\n        \"denied\": \"權限被拒絕\"\n      },\n      \"export\": {\n        \"clipboard\": {\n          \"success\": \"已成功新增至剪貼簿\",\n          \"failure\": \"複製到剪貼簿失敗\",\n          \"contentTooLarge\": \"內容過大，請改用匯出檔案\"\n        },\n        \"file\": {\n          \"success\": \"JSON 檔案建立成功\",\n          \"failure\": \"建立檔案失敗\"\n        }\n      },\n      \"import\": {\n        \"confirm\": \"確認匯入\",\n        \"success\": \"匯入成功\",\n        \"failure\": \"匯入失敗\"\n      }\n    }\n  },\n  \"intro\": {\n    \"banner\": \"暢享無限制網路的所需一切\",\n    \"termsAndPolicyCaution(rich)\": \"繼續即表示您同意 ${tap(@:pages.about.termsAndConditions)}\",\n    \"info(rich)\": \"由 Hiddify 以 ❤️ 製作 - ${tap_source(開源)} (${tap_license(授權)})\"\n  },\n  \"pages\": {\n    \"home\": {\n      \"title\": \"首頁\",\n      \"quickSettings\": \"快速設定\"\n    },\n    \"proxies\": {\n      \"title\": \"代理\",\n      \"sort\": \"排序代理\",\n      \"testDelay\": \"測試延遲\",\n      \"empty\": \"無可用代理\",\n      \"activeProxy\": \"當前代理\",\n      \"unknownIp\": \"未知 IP\",\n      \"sortOptions\": {\n        \"unsorted\": \"預設\",\n        \"name\": \"按名稱\",\n        \"delay\": \"按延遲\"\n      },\n      \"ipInfo\": {\n        \"address\": \"IP 位址\",\n        \"country\": \"國家\",\n        \"organization\": \"組織\"\n      },\n      \"delay\": {\n        \"result\": \"延遲：${delay}毫秒\",\n        \"timeout\": \"延遲測試超時\",\n        \"testing\": \"延遲：測試中...\"\n      }\n    },\n    \"profiles\": {\n      \"title\": \"設定檔\",\n      \"add\": \"新增設定檔\",\n      \"update\": \"更新設定檔\",\n      \"viewAllProfiles\": \"檢視所有設定檔\",\n      \"activeProfileName\": \"目前設定檔：「${name}」\",\n      \"nonActiveProfileName\": \"選擇「${name}」作為目前設定檔\",\n      \"freeSubNotFound\": \"未找到免費訂閱\",\n      \"freeSubNotFoundForRegion\": \"未找到「${region}」地區的免費訂閱\",\n      \"failedToLoad\": \"載入失敗\",\n      \"updateSubscriptions\": \"更新訂閱\",\n      \"share\": {\n        \"urlToClipboard\": \"URL 到剪貼簿\",\n        \"showUrlQr\": \"顯示 URL QR Code\",\n        \"jsonToClipboard\": \"JSON 到剪貼簿\"\n      },\n      \"msg\": {\n        \"save\": {\n          \"success\": \"設定檔儲存成功\"\n        },\n        \"invalidUrl\": \"無效的 URL\",\n        \"add\": {\n          \"failure\": \"新增設定檔失敗\"\n        },\n        \"update\": {\n          \"success\": \"設定檔更新成功\",\n          \"successNamed\": \"「${name}」更新成功\",\n          \"failure\": \"更新設定檔失敗\",\n          \"failureNamed\": \"更新「${name}」失敗\"\n        },\n        \"delete\": {\n          \"success\": \"設定檔刪除成功\"\n        }\n      }\n    },\n    \"profileDetails\": {\n      \"title\": \"設定檔\",\n      \"lastUpdate\": \"最後更新\",\n      \"form\": {\n        \"nameHint\": \"設定檔名稱\",\n        \"emptyName\": \"名稱為必填項\",\n        \"invalidUrl\": \"無效的 URL\",\n        \"urlHint\": \"完整的設定 URL\",\n        \"disableAutoUpdate\": \"停用自動更新\",\n        \"autoUpdateInterval\": \"自動更新間隔\",\n        \"loading\": \"正在新增設定檔...\"\n      }\n    },\n    \"logs\": {\n      \"title\": \"日誌\",\n      \"shareCoreLogs\": \"分享核心日誌\",\n      \"shareAppLogs\": \"分享應用程式日誌\"\n    },\n    \"about\": {\n      \"title\": \"關於\",\n      \"notAvailableMsg\": \"已是最新版本\",\n      \"checkForUpdate\": \"檢查更新\",\n      \"openWorkingDir\": \"開啟工作目錄\",\n      \"sourceCode\": \"原始碼\",\n      \"telegramChannel\": \"Telegram 頻道\",\n      \"termsAndConditions\": \"條款與條件\",\n      \"privacyPolicy\": \"隱私權政策\"\n    },\n    \"settings\": {\n      \"title\": \"設定\",\n      \"resetTunnel\": \"重設 VPN 設定檔\",\n      \"options\": {\n        \"import\": {\n          \"clipboard\": \"從剪貼簿匯入選項\",\n          \"file\": \"從檔案匯入選項\"\n        },\n        \"export\": {\n          \"anonymousToClipboard\": \"複製匿名選項到剪貼簿\",\n          \"anonymousToFile\": \"匯出匿名選項到檔案\",\n          \"allToClipboard\": \"複製所有選項到剪貼簿\",\n          \"allToFile\": \"匯出所有選項到檔案\"\n        },\n        \"reset\": \"重設選項\"\n      },\n      \"general\": {\n        \"title\": \"一般\",\n        \"locale\": \"語言\",\n        \"themeMode\": \"主題模式\",\n        \"themeModes\": {\n          \"system\": \"跟隨系統\",\n          \"dark\": \"深色模式\",\n          \"light\": \"淺色模式\",\n          \"black\": \"純黑模式\"\n        },\n        \"enableAnalytics\": \"啟用分析\",\n        \"enableAnalyticsMsg\": \"允許收集分析資料和傳送崩潰報告以改進應用程式\",\n        \"autoIpCheck\": \"自動檢查連線 IP\",\n        \"dynamicNotification\": \"在通知中顯示速度\",\n        \"hapticFeedback\": \"觸覺回饋\",\n        \"actionAtClosing\": \"關閉時操作\",\n        \"autoStart\": \"開機自啟\",\n        \"silentStart\": \"靜默啟動\",\n        \"ignoreBatteryOptimizations\": \"忽略電池最佳化\",\n        \"ignoreBatteryOptimizationsMsg\": \"移除限制以獲得最佳 VPN 效能\",\n        \"memoryLimit\": \"記憶體限制\",\n        \"memoryLimitMsg\": \"如果您遇到記憶體不足錯誤或應用程式頻繁崩潰，請啟用此選項\",\n        \"debugMode\": \"偵錯模式\",\n        \"debugModeMsg\": \"重新啟動應用程式以套用此變更\",\n        \"logLevel\": \"日誌級別\",\n        \"connectionTestUrl\": \"連線測試 URL\",\n        \"urlTestInterval\": \"URL 測試間隔\",\n        \"clashApiPort\": \"Clash API 連接埠\",\n        \"useXrayCoreWhenPossible\": \"盡可能使用 xray-core\",\n        \"useXrayCoreWhenPossibleMsg\": \"解析訂閱連結時使用 xray-core。您需要重新匯入訂閱連結才能啟用此選項\"\n      },\n      \"routing\": {\n        \"title\": \"路由\",\n        \"perAppProxy\": {\n          \"title\": \"依應用程式代理\",\n          \"hideSysApps\": \"隱藏系統應用程式\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"從剪貼簿匯入選擇\",\n              \"file\": \"從檔案匯入選擇\",\n              \"msg\": \"匯入將取代您目前的選擇。確定要繼續嗎？\"\n            },\n            \"export\": {\n              \"clipboard\": \"複製選擇到剪貼簿\",\n              \"file\": \"匯出選擇到檔案\"\n            },\n            \"shareToAll\": \"分享給所有人\",\n            \"clearAllSelections\": \"清除所有選擇\"\n          },\n          \"modes\": {\n            \"all\": \"全部\",\n            \"proxy\": \"代理\",\n            \"bypass\": \"繞過\",\n            \"allMsg\": \"代理所有應用程式\",\n            \"proxyMsg\": \"僅代理選定應用程式\",\n            \"bypassMsg\": \"不代理選定應用程式\"\n          },\n          \"autoSelection\": {\n            \"title\": \"自動選擇\",\n            \"performNow\": \"立即執行\",\n            \"resetToDefault\": \"重設為預設\",\n            \"autoUpdateInterval\": \"自動更新間隔\",\n            \"toast\": {\n              \"success\": \"自動選擇應用程式成功完成\",\n              \"failure\": \"自動選擇失敗\",\n              \"regionNotFound\": \"未找到「${region}」地區的自動選擇\",\n              \"alreadyInAuto\": \"您的選擇已在自動清單中\"\n            },\n            \"dialog\": {\n              \"title\": \"自動選擇應用程式\",\n              \"msg\": \"由於地區更改為「${region}」，依應用程式代理的自動選擇功能已被停用\"\n            }\n          }\n        },\n        \"region\": \"地區\",\n        \"regions\": {\n          \"ir\": \"伊朗 (ir)\",\n          \"cn\": \"中國 (cn)\",\n          \"ru\": \"俄羅斯 (ru)\",\n          \"af\": \"阿富汗 (af)\",\n          \"id\": \"印尼 (id)\",\n          \"tr\": \"土耳其 (tr)\",\n          \"br\": \"巴西 (br)\",\n          \"other\": \"其他\"\n        },\n        \"balancerStrategy\": {\n          \"title\": \"Balancer 策略\",\n          \"roundRobin\": \"Round robin\",\n          \"consistentHash\": \"Consistent hash\",\n          \"stickySession\": \"Sticky session\"\n        },\n        \"blockAds\": \"攔截廣告\",\n        \"bypassLan\": \"繞過區域網路\",\n        \"resolveDestination\": \"解析目的地\",\n        \"ipv6Route\": \"IPv6 路由\",\n        \"ipv6Modes\": {\n          \"disable\": \"停用\",\n          \"enable\": \"啟用\",\n          \"prefer\": \"首選\",\n          \"only\": \"僅\"\n        },\n        \"routeRule\": {\n          \"title\": \"路由規則\",\n          \"options\": {\n            \"import\": {\n              \"clipboard\": \"從剪貼簿匯入規則\",\n              \"file\": \"從檔案匯入規則\"\n            },\n            \"export\": {\n              \"clipboard\": \"複製規則到剪貼簿\",\n              \"file\": \"儲存規則到檔案\"\n            },\n            \"reset\": \"重設規則\"\n          },\n          \"deleteRule\": \"刪除規則\",\n          \"createRule\": \"建立新規則\",\n          \"rule\": {\n            \"title\": \"規則\",\n            \"ruleChanged\": \"規則已變更\",\n            \"ruleChangedMsg\": \"您想儲存您的編輯嗎？\",\n            \"onlyTunMode\": \"僅在 TUN 模式下可用\",\n            \"notAvailabeInThisPlatform\": \"在此平台上不可用\",\n            \"canNotBeEmpty\": \"不能為空\",\n            \"validUrlEx\": \"https://example.com\",\n            \"validUrl\": \"有效的「URL」，例如\\n@:pages.settings.routing.routeRule.rule.validUrlEx\",\n            \"validProcessNameEx\": \"Chrome.exe 或 google chrome 或 chrome\",\n            \"validProcessName\": \"有效的「處理程序名稱」，例如\\n@:pages.settings.routing.routeRule.rule.validProcessNameEx\",\n            \"validProcessPathEx\": \"C:\\\\Pro...\\\\chrome.exe\\n/App.../Google Chrome\\n/usr/lib.../chrome\",\n            \"validProcessPath\": \"有效的「處理程序路徑」，例如\\n@:pages.settings.routing.routeRule.rule.validProcessPathEx\",\n            \"validPortRangeEx\": \"80 或 1-65000\",\n            \"validPortRange\": \"有效的「連接埠」或「連接埠範圍」，例如\\n@:pages.settings.routing.routeRule.rule.validPortRangeEx\",\n            \"validIpCidrEx\": \"8.8.8.8 或 10.0.0.0/24\",\n            \"validIpCidr\": \"有效的 IP CIDR，例如\\n@:pages.settings.routing.routeRule.rule.validIpCidrEx\",\n            \"validDomainEx\": \"Google.com 或 dl.google.com\",\n            \"validDomain\": \"有效的「網域」，例如\\n@:pages.settings.routing.routeRule.rule.validDomainEx\",\n            \"validDomainSuffixEx\": \".com 或 .tw\",\n            \"validDomainSuffix\": \"有效的「網域後綴」，例如\\n@:pages.settings.routing.routeRule.rule.validDomainSuffixEx\",\n            \"tileTitle(map)\": {\n              \"name\": \"名稱\",\n              \"outbound\": \"符合時出站\",\n              \"rule_set\": \"規則集 URL\",\n              \"package_name\": \"套件名稱\",\n              \"process_name\": \"處理程序名稱\",\n              \"process_path\": \"處理程序路徑\",\n              \"network\": \"網路\",\n              \"port_range\": \"目標連接埠\",\n              \"source_port_range\": \"來源連接埠\",\n              \"protocol\": \"協定\",\n              \"ip_cidr\": \"目標 IP CIDR\",\n              \"source_ip_cidr\": \"來源 IP CIDR\",\n              \"domain\": \"網域\",\n              \"domain_suffixe\": \"網域後綴\",\n              \"domain_keyword\": \"網域關鍵字\",\n              \"domain_regex\": \"網域正規表示式\"\n            },\n            \"outbound(map)\": {\n              \"proxy\": \"代理\",\n              \"direct\": \"直連\",\n              \"direct_with_fragment\": \"直連並分片\",\n              \"block\": \"攔截\"\n            },\n            \"network(map)\": {\n              \"all\": \"全部\",\n              \"tcp\": \"TCP\",\n              \"udp\": \"UDP\"\n            },\n            \"protocol(map)\": {\n              \"\": \"全部\",\n              \"tls\": \"TLS\",\n              \"http\": \"HTTP\",\n              \"quic\": \"QUIC\",\n              \"stun\": \"STUN\",\n              \"dns\": \"DNS\",\n              \"bittorrent\": \"BitTorrent\"\n            }\n          },\n          \"genericList\": {\n            \"addNew\": \"新增值\",\n            \"update\": \"更新值\",\n            \"clearList\": \"清除清單\",\n            \"clearListMsg\": \"所有項目已刪除\"\n          },\n          \"androidApps\": {\n            \"pageTitle\": \"Android 應用程式\",\n            \"showSystemApps\": \"顯示系統應用程式\",\n            \"hideSystemApps\": \"隱藏系統應用程式\",\n            \"clearSelection\": \"清除選擇\",\n            \"uninstalled\": \"已解除安裝\"\n          }\n        }\n      },\n      \"dns\": {\n        \"title\": \"DNS\",\n        \"remoteDns\": \"遠端 DNS\",\n        \"remoteDnsDomainStrategy\": \"遠端 DNS 網域策略\",\n        \"directDns\": \"出站伺服器解析器（直連）\",\n        \"directDnsDomainStrategy\": \"出站網域策略\",\n        \"enableDnsRouting\": \"啟用 DNS 路由\",\n        \"enableFakeDns\": \"啟用偽造 DNS\",\n        \"domainStrategy\": {\n          \"auto\": \"自動\",\n          \"preferIpv6\": \"偏好 IPv6\",\n          \"preferIpv4\": \"偏好 IPv4\",\n          \"ipv4Only\": \"僅 IPv4\",\n          \"ipv6Only\": \"僅 IPv6\"\n        }\n      },\n      \"inbound\": {\n        \"title\": \"入站\",\n        \"serviceMode\": \"服務模式\",\n        \"serviceModes\": {\n          \"proxy\": \"僅代理服務\",\n          \"systemProxy\": \"設定系統代理\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"VPN 服務\"\n        },\n        \"shortServiceModes\": {\n          \"proxy\": \"代理\",\n          \"systemProxy\": \"系統代理\",\n          \"tun\": \"VPN\",\n          \"tunService\": \"VPN 服務\"\n        },\n        \"strictRoute\": \"嚴格路由\",\n        \"tunImplementation\": \"TUN 實現\",\n        \"tunImplementations\": {\n          \"mixed\": \"混合\",\n          \"system\": \"系統\",\n          \"gvisor\": \"gVisor\"\n        },\n        \"mixedPort\": \"混合連接埠\",\n        \"tproxyPort\": \"透明代理連接埠\",\n        \"directPort\": \"本地 Direct 連接埠\",\n        \"redirectPort\": \"重新導向連接埠\",\n        \"allowConnectionFromLan\": \"允許來自區域網路的連線\"\n      },\n      \"tlsTricks\": {\n        \"title\": \"TLS 技巧\",\n        \"enable\": \"啟用分片\",\n        \"packets\": \"分片封包\",\n        \"packetsTlsHello\": \"TLS Hello\",\n        \"packets1_1\": \"1-1\",\n        \"packets1_2\": \"1-2\",\n        \"packets1_3\": \"1-3\",\n        \"packets1_4\": \"1-4\",\n        \"packets1_5\": \"1-5\",\n        \"size\": \"分片大小\",\n        \"sleep\": \"分片延遲\",\n        \"mixedSniCase\": {\n          \"enable\": \"啟用混合大小寫 SNI\"\n        },\n        \"padding\": {\n          \"enable\": \"啟用填充\",\n          \"size\": \"填充大小\"\n        }\n      },\n      \"warp\": {\n        \"title\": \"WARP\",\n        \"enable\": \"啟用 WARP\",\n        \"generateConfig\": \"產生 WARP 設定\",\n        \"configGenerated\": \"WARP 設定已產生\",\n        \"missingConfig\": \"WARP 設定缺失\",\n        \"detourMode\": \"WARP 路由模式\",\n        \"detourModes\": {\n          \"proxyOverWarp\": \"透過 WARP 路由代理\",\n          \"warpOverProxy\": \"透過代理路由 WARP\",\n          \"proxyOverWarpExplain\": \"透過 WARP 解鎖代理\",\n          \"warpOverProxyExplain\": \"透過 WARP 增強安全性\"\n        },\n        \"licenseKey\": \"授權金鑰\",\n        \"cleanIp\": \"優選 IP\",\n        \"port\": \"連接埠\",\n        \"noise\": {\n          \"count\": \"噪音數量\",\n          \"mode\": \"噪音模式\",\n          \"size\": \"噪音大小\",\n          \"delay\": \"噪音延遲\"\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"stats\": {\n      \"connection\": \"連線\",\n      \"traffic\": \"流量\",\n      \"trafficLive\": \"即時流量\",\n      \"trafficTotal\": \"總流量\",\n      \"uplink\": \"上傳\",\n      \"downlink\": \"下載\",\n      \"speed\": \"速度\",\n      \"totalTransferred\": \"總傳輸量\"\n    },\n    \"subscriptionInfo\": {\n      \"upload\": \"上傳\",\n      \"download\": \"下載\",\n      \"total\": \"總流量\",\n      \"expireDate\": \"到期日期\",\n      \"expired\": \"已到期\",\n      \"noTraffic\": \"流量已用盡\",\n      \"remainingTime\": \"剩餘時間\",\n      \"remainingDuration\": \"剩餘 ${duration} 天\",\n      \"remainingDurationNew\": \"${duration} 天\",\n      \"remainingTrafficSemanticLabel\": \"已使用 ${consumed} / ${total} 流量\",\n      \"remainingTraffic\": \"剩餘流量\",\n      \"remainingUsage\": \"剩餘\",\n      \"profileSite\": \"提供商\",\n      \"profileSupport\": \"支援\"\n    }\n  },\n  \"dialogs\": {\n    \"sortProfiles\": {\n      \"title\": \"排序方式\",\n      \"sort\": {\n        \"name\": \"按字母順序\",\n        \"lastUpdate\": \"最近更新\"\n      }\n    },\n    \"warpLicense\": {\n      \"title\": \"Cloudflare WARP 同意書\",\n      \"description(rich)\": \"Cloudflare WARP 是一個免費的 WireGuard VPN 提供商。啟用此選項即表示您同意 Cloudflare WARP 的 ${tos(服務條款)} 和 ${privacy(隱私權政策)}。\"\n    },\n    \"newVersion\": {\n      \"title\": \"有可用更新\",\n      \"msg\": \"@:common.appTitle 的新版本已發布。您想立即更新嗎？\",\n      \"currentVersion\": \"目前版本：\",\n      \"newVersion\": \"新版本：\",\n      \"updateNow\": \"立即更新\"\n    },\n    \"confirmation\": {\n      \"settings\": {\n        \"import\": {\n          \"msg\": \"這會使用提供的值覆蓋所有設定選項。您確定嗎？\"\n        }\n      },\n      \"profile\": {\n        \"delete\": {\n          \"title\": \"刪除設定檔\",\n          \"msg\": \"您確定要永久刪除此設定檔嗎？\"\n        }\n      },\n      \"perAppProxy\": {\n        \"shareOnGithub\": {\n          \"title\": \"改進自動選擇\",\n          \"msg\": \"透過分享您選擇的應用程式，可以幫助完善「自動選擇」清單\"\n        },\n        \"import\": {\n          \"msg\": \"這將取代您目前所有的依應用程式代理選擇。您確定要繼續嗎？\"\n        }\n      },\n      \"routeRule\": {\n        \"delete\": {\n          \"title\": \"刪除規則\",\n          \"msg\": \"您確定要刪除規則「$rulename」嗎？\"\n        }\n      }\n    },\n    \"experimentalNotice\": {\n      \"title\": \"正在使用實驗性功能\",\n      \"msg\": \"您已啟用了一些實驗性功能，這可能會影響連線品質並導致意外錯誤。您可以隨時在設定選項頁面變更或重設這些選項。\",\n      \"disable\": \"不再顯示\"\n    },\n    \"noActiveProfile\": {\n      \"title\": \"選擇一個設定檔\",\n      \"msg\": \"讓我們從新增一個包含您 VPN 連線詳細資訊的設定檔開始。\\n\\n還沒有 VPN 伺服器？別擔心，按照下面的教學，您可以快速免費地設定一個。\",\n      \"helpBtn\": {\n        \"label\": \"告訴我如何操作\",\n        \"url\": \"https://hiddify.com/manager/\"\n      }\n    },\n    \"unknownDomainsWarning\": {\n      \"title\": \"外部連結警告\",\n      \"youAreAboutToVisit\": \"您即將造訪：\",\n      \"thisWebsiteIsNotInOurTrustedList\": \"此網站不在我們的信任清單中。請謹慎操作。\"\n    },\n    \"proxyInfo\": {\n      \"fullTag\": \"完整標籤：\",\n      \"type\": \"類型：\",\n      \"testTime\": \"測試時間：\",\n      \"testDelay\": \"測試延遲：\",\n      \"isSelected\": \"已選擇：\",\n      \"isGroup\": \"是群組\",\n      \"isSecure\": \"安全：\",\n      \"port\": \"連接埠：\",\n      \"host\": \"主機：\",\n      \"ip\": \"IP：\",\n      \"countryCode\": \"國家代碼：\",\n      \"region\": \"地區：\",\n      \"city\": \"城市：\",\n      \"asn\": \"ASN：\",\n      \"organization\": \"組織：\",\n      \"location\": \"位置：\",\n      \"postalCode\": \"郵遞區號：\"\n    },\n    \"windowClosing\": {\n      \"askEachTime\": \"每次詢問\",\n      \"alertMessage\": \"隱藏還是退出應用程式？\",\n      \"remember\": \"記住我的選擇\"\n    }\n  },\n  \"connection\": {\n    \"tapToConnect\": \"點擊連線\",\n    \"connect\": \"連線\",\n    \"connecting\": \"連線中...\",\n    \"connected\": \"已連線\",\n    \"disconnect\": \"中斷連線\",\n    \"disconnecting\": \"中斷連線中...\",\n    \"reconnect\": \"重新連線\",\n    \"reconnectMsg\": \"正在重新連線以套用變更...\",\n    \"secure\": \"由 WARP 保護\"\n  },\n  \"errors\": {\n    \"unexpected\": \"意外錯誤\",\n    \"connection\": {\n      \"unexpected\": \"意外連線錯誤\",\n      \"timeout\": \"連線超時\",\n      \"badResponse\": \"回應錯誤\",\n      \"connectionError\": \"連線錯誤\",\n      \"badCertificate\": \"憑證無效\"\n    },\n    \"profiles\": {\n      \"unexpected\": \"意外錯誤\",\n      \"notFound\": \"未找到設定檔\",\n      \"invalidConfig\": \"設定無效\",\n      \"invalidUrl\": \"URL 無效\",\n      \"canceledByUser\": \"使用者已取消\"\n    },\n    \"connectivity\": {\n      \"unexpected\": \"意外失敗\",\n      \"missingVpnPermission\": \"缺少 VPN 權限\",\n      \"missingNotificationPermission\": \"缺少通知權限\",\n      \"core\": \"核心錯誤\"\n    },\n    \"singbox\": {\n      \"serviceNotRunning\": \"服務未運行\",\n      \"missingPrivilege\": \"缺少權限\",\n      \"missingPrivilegeMsg\": \"VPN 模式需要管理員權限。請以管理員身份重新啟動應用，或更改服務模式。\",\n      \"invalidConfigOptions\": \"設定選項無效\",\n      \"invalidConfig\": \"設定無效\"\n    },\n    \"warp\": {\n      \"missingLicense\": \"WARP 授權缺失\",\n      \"missingLicenseMsg\": \"所選設定檔使用 WARP 功能；要使用此功能，必須同意 WARP 授權條款。\"\n    }\n  }\n}"
  },
  {
    "path": "build.yaml",
    "content": "targets:\n  $default:\n    builders:\n      json_serializable:\n        options:\n          explicit_to_json: true\n      drift_dev:\n        options:\n          databases:\n            db: \"lib/core/db/db.dart\"\n          schema_dir: \"lib/core/db/schemas\"\n          store_date_time_values_as_text: true\n      slang_build_runner:\n        options:\n          base_locale: en\n          fallback_strategy: base_locale\n          input_directory: assets/translations\n          input_file_pattern: .i18n.json\n          output_directory: lib/gen\n          output_file_name: translations.g.dart\n          translation_class_visibility: public\n          locale_handling: false\n      # protoc_builder:\n      #   options:\n      #     protobuf_version: \"3.1.0\"\n      #     protoc_plugin_version: \"21.1.2\"\n      #     root_dir: \"assets/proto\"\n      #     proto_paths:\n      #       - \"assets/proto\"\n      #     out_dir: \"lib/gen/proto\"\n      #     use_installed_protoc: true\n      #     precompile_protoc_plugin: false\n"
  },
  {
    "path": "dependencies.properties",
    "content": "core.version=4.1.0"
  },
  {
    "path": "devtools_options.yaml",
    "content": "extensions:\n"
  },
  {
    "path": "ios/.gitignore",
    "content": "**/dgph\n*.mode1v3\n*.mode2v3\n*.moved-aside\n*.pbxuser\n*.perspectivev3\n**/*sync/\n.sconsign.dblite\n.tags*\n**/.vagrant/\n**/DerivedData/\nIcon?\n**/Pods/\n**/.symlinks/\nprofile\nxcuserdata\n**/.generated/\nFlutter/App.framework\nFlutter/Flutter.framework\nFlutter/Flutter.podspec\nFlutter/Generated.xcconfig\nFlutter/ephemeral/\nFlutter/app.flx\nFlutter/app.zip\nFlutter/flutter_assets/\nFlutter/flutter_export_environment.sh\nServiceDefinitions.json\nRunner/GeneratedPluginRegistrant.*\n\n# Exceptions to above rules.\n!default.mode1v3\n!default.mode2v3\n!default.pbxuser\n!default.perspectivev3\n"
  },
  {
    "path": "ios/.stignore",
    "content": "/**/dgph\n/*.mode1v3\n/*.mode2v3\n/*.moved-aside\n/*.pbxuser\n/*.perspectivev3\n/**/*sync/\n/.sconsign.dblite\n/.tags*\n/**/.vagrant/\n/**/DerivedData/\n/Icon?\n/**/Pods/\n/**/.symlinks/\n/profile\n/xcuserdata\n/**/.generated/\n/Flutter/App.framework\n/Flutter/Flutter.framework\n/Flutter/Flutter.podspec\n/Flutter/Generated.xcconfig\n/Flutter/ephemeral/\n/Flutter/app.flx\n/Flutter/app.zip\n/Flutter/flutter_assets/\n/Flutter/flutter_export_environment.sh\n/ServiceDefinitions.json\n/Runner/GeneratedPluginRegistrant.*\n\n!default.mode1v3\n!default.mode2v3\n!default.pbxuser\n!default.perspectivev3\n"
  },
  {
    "path": "ios/Base.xcconfig",
    "content": "//\n//  Base.xcconfig\n//  Runner\n//\n//  Created by GFWFighter on 7/24/1402 AP.\n//\n\nBASE_BUNDLE_IDENTIFIER=apple.hiddify.com\nSERVICE_IDENTIFIER=com.hiddify.app\nDEVELOPMENT_TEAM=3JFTY5BP58\n"
  },
  {
    "path": "ios/Flutter/AppFrameworkInfo.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n  <key>CFBundleDevelopmentRegion</key>\n  <string>en</string>\n  <key>CFBundleExecutable</key>\n  <string>App</string>\n  <key>CFBundleIdentifier</key>\n  <string>io.flutter.flutter.app</string>\n  <key>CFBundleInfoDictionaryVersion</key>\n  <string>6.0</string>\n  <key>CFBundleName</key>\n  <string>App</string>\n  <key>CFBundlePackageType</key>\n  <string>FMWK</string>\n  <key>CFBundleShortVersionString</key>\n  <string>1.0</string>\n  <key>CFBundleSignature</key>\n  <string>????</string>\n  <key>CFBundleVersion</key>\n  <string>1.0</string>\n  <key>MinimumOSVersion</key>\n  <string>15.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Flutter/Debug.xcconfig",
    "content": "#include? \"Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"\n#include \"Generated.xcconfig\"\n\n#include \"Base.xcconfig\"\n"
  },
  {
    "path": "ios/Flutter/Release.xcconfig",
    "content": "#include? \"Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"\n#include \"Generated.xcconfig\"\n\n#include \"Base.xcconfig\"\n"
  },
  {
    "path": "ios/Frameworks/.gitkeep",
    "content": ""
  },
  {
    "path": "ios/HiddifyPacketTunnel/HiddifyPacketTunnel.entitlements",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n    <key>com.apple.developer.networking.networkextension</key>\n    <array>\n        <string>app-proxy-provider</string>\n        <string>dns-proxy</string>\n        <string>packet-tunnel-provider</string>\n        <string>content-filter-provider</string>\n    </array>\n    <key>com.apple.security.app-sandbox</key>\n    <true/>\n    <key>com.apple.security.application-groups</key>\n    <array>\n        <string>group.$(BASE_BUNDLE_IDENTIFIER)</string>\n    </array>\n    <key>com.apple.security.network.client</key>\n    <true/>\n    <key>com.apple.security.network.server</key>\n    <true/>\n    <key>com.apple.developer.networking.vpn.api</key>\n    <array>\n        <string>allow-vpn</string>\n    </array>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/HiddifyPacketTunnel/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BASE_BUNDLE_IDENTIFIER</key>\n\t<string>$(BASE_BUNDLE_IDENTIFIER)</string>\n\t<key>NSExtension</key>\n\t<dict>\n\t\t<key>NSExtensionPointIdentifier</key>\n\t\t<string>com.apple.networkextension.packet-tunnel</string>\n\t\t<key>NSExtensionPrincipalClass</key>\n\t\t<string>$(PRODUCT_MODULE_NAME).PacketTunnelProvider</string>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/HiddifyPacketTunnel/Logger.swift",
    "content": "//\n//  Logger.swift\n//  SingBoxPacketTunnel\n//\n//  Created by GFWFighter on 10/24/23.\n//\n\nimport Foundation\n\nclass Logger2 {\n    private static let queue = DispatchQueue.init(label: \"\\(FilePath.packageName).PacketTunnelLog\", qos: .utility)\n    \n    private let fileManager = FileManager.default\n    private let url: URL\n    \n    private var _fileHandle: FileHandle?\n    private var fileHandle: FileHandle? {\n        get {\n            if let _fileHandle { return _fileHandle }\n            let handle = try? FileHandle(forWritingTo: url)\n            _fileHandle = handle\n            return handle\n        }\n    }\n    \n    private var lock = NSLock()\n    \n    init(path: URL) {\n        url = path\n    }\n    \n    func write(_ message: String) {\n        Logger2.queue.async { [message, unowned self] () in\n            lock.lock()\n            defer { lock.unlock() }\n            let output = message + \"\\n\"\n            do {\n                if !self.fileManager.fileExists(atPath: url.path) {\n                    try output.write(to: url, atomically: true, encoding: .utf8)\n                } else {\n                    guard let fileHandle else {\n                        return\n                    }\n                    fileHandle.seekToEndOfFile()\n                    if let data = output.data(using: .utf8) {\n                        fileHandle.write(data)\n                    }\n                }\n            } catch {}\n        }\n    }\n}\n"
  },
  {
    "path": "ios/HiddifyPacketTunnel/PacketTunnelProvider.swift",
    "content": "//\n//  PacketTunnelProvider.swift\n//  SingBoxPacketTunnel\n//\n//  Created by GFWFighter on 7/24/1402 AP.\n//\n\nimport NetworkExtension\n\nclass PacketTunnelProvider: ExtensionProvider {\n\n    private var upload: Int64 = 0\n    private var download: Int64 = 0\n    // private var trafficLock: NSLock = NSLock()\n    \n    // var trafficReader: TrafficReader!\n    \n    override func startTunnel(options: [String : NSObject]?) async throws {\n//    override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {\n\n        NSLog(\"H?C1\")\n        try await super.startTunnel(options: options)\n        /*trafficReader = TrafficReader { [unowned self] traffic in\n            trafficLock.lock()\n            upload += traffic.up\n            download += traffic.down\n            trafficLock.unlock()\n        }*/\n    }\n    \n    override func handleAppMessage(_ messageData: Data) async -> Data? {\n        \n        let message = String(data: messageData, encoding: .utf8)\n//        NSLog(\"H?C2\"+message??\"\")\n        switch message {\n        case \"stats\":\n            return \"\\(upload),\\(download)\".data(using: .utf8)!\n        default:\n            return nil\n        }\n    }\n}\n"
  },
  {
    "path": "ios/HiddifyPacketTunnel/PrivacyInfo.xcprivacy",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>NSPrivacyAccessedAPITypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>C617.1</string>\n\t\t\t</array>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategorySystemBootTime</string>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>35F9.1</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/HiddifyPacketTunnel/SingBox/Extension+RunBlocking.swift",
    "content": "//\n//  Extension+RunBlocking.swift\n//  SingBoxPacketTunnel\n//\n//  Created by GFWFighter on 7/25/1402 AP.\n//\n\nimport Foundation\nimport HiddifyCore\nimport NetworkExtension\n\nfunc runBlocking<T>(_ block: @escaping () async -> T) -> T {\n    let semaphore = DispatchSemaphore(value: 0)\n    let box = resultBox<T>()\n    Task.detached {\n        let value = await block()\n        box.result0 = value\n        semaphore.signal()\n    }\n    semaphore.wait()\n    return box.result0\n}\n\nfunc runBlocking<T>(_ tBlock: @escaping () async throws -> T) throws -> T {\n    let semaphore = DispatchSemaphore(value: 0)\n    let box = resultBox<T>()\n    Task.detached {\n        do {\n            let value = try await tBlock()\n            box.result = .success(value)\n        } catch {\n            box.result = .failure(error)\n        }\n        semaphore.signal()\n    }\n    semaphore.wait()\n    return try box.result.get()\n}\n\nprivate class resultBox<T> {\n    var result: Result<T, Error>!\n    var result0: T!\n}\n"
  },
  {
    "path": "ios/HiddifyPacketTunnel/SingBox/ExtensionPlatformInterface.swift",
    "content": "//\n//  ExtensionPlatformInterface.swift\n//  SingBoxPacketTunnel\n//\n//  Created by GFWFighter on 7/25/1402 AP.\n//\n\nimport Foundation\nimport HiddifyCore\nimport NetworkExtension\n\npublic class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtocol {\n    \n    \n    private var tunnel: ExtensionProvider\n    private var networkSettings: NEPacketTunnelNetworkSettings?\n\n    init(_ tunnel: ExtensionProvider) {\n        self.tunnel = tunnel\n    }\n\n    public func openTun(_ options: LibboxTunOptionsProtocol?, ret0_: UnsafeMutablePointer<Int32>?) throws {\n        NSLog(\"H?A1\")\n        try runBlocking { [self] in\n            try await openTun0(options, ret0_)\n        }\n    }\n\n    private func openTun0(_ options: LibboxTunOptionsProtocol?, _ ret0_: UnsafeMutablePointer<Int32>?) async throws {\n        guard let options else {\n            throw NSError(domain: \"ExtensionPlatformInterface\", code: 0, userInfo: [NSLocalizedDescriptionKey: String(localized: \"Nil options\")])\n        }\n        guard let ret0_ else {\n            throw NSError(domain: \"ExtensionPlatformInterface\", code: 0, userInfo: [NSLocalizedDescriptionKey: String(localized: \"Nil return pointer\")])\n        }\n\n//        let prefs = tunnel.overridePreferences ?? ExtensionProvider.OverridePreferences()\n        let autoRouteUseSubRangesByDefault = true//prefs.autoRouteUseSubRangesByDefault // await SharedPreferences.autoRouteUseSubRangesByDefault.get()\n        let excludeAPNs = false//prefs.excludeAPNsRoute //await SharedPreferences.excludeAPNsRoute.get()\n        let excludeDefaultRoute = false// prefs.excludeDefaultRoute\n        let systemProxyEnabled = false//prefs.systemProxyEnabled\n\n        \n        let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: \"::1\")\n        if options.getAutoRoute() {\n            settings.mtu = NSNumber(value: options.getMTU())\n\n           let dnsServer = try options.getDNSServerAddress()\n            let dnsSettings = NEDNSSettings(servers: [dnsServer.value,\"fdfe:dcba:9876::1\"])\n            dnsSettings.matchDomains = [\"\"]\n            dnsSettings.matchDomainsNoSearch = true\n            settings.dnsSettings = dnsSettings\n            \n            var ipv4Address: [String] = []\n            var ipv4Mask: [String] = []\n            let ipv4AddressIterator = options.getInet4Address()!\n            while ipv4AddressIterator.hasNext() {\n                let ipv4Prefix = ipv4AddressIterator.next()!\n                ipv4Address.append(ipv4Prefix.address())\n                ipv4Mask.append(ipv4Prefix.mask())\n            }\n            let ipv4Settings = NEIPv4Settings(addresses: ipv4Address, subnetMasks: ipv4Mask)\n            var ipv4Routes: [NEIPv4Route] = []\n            var ipv4ExcludeRoutes: [NEIPv4Route] = []\n\n            let inet4RouteAddressIterator = options.getInet4RouteAddress()!\n            if inet4RouteAddressIterator.hasNext() {\n                while inet4RouteAddressIterator.hasNext() {\n                    let ipv4RoutePrefix = inet4RouteAddressIterator.next()!\n                    ipv4Routes.append(NEIPv4Route(destinationAddress: ipv4RoutePrefix.address(), subnetMask: ipv4RoutePrefix.mask()))\n                }\n            } else if autoRouteUseSubRangesByDefault {\n                ipv4Routes.append(NEIPv4Route(destinationAddress: \"1.0.0.0\", subnetMask: \"255.0.0.0\"))\n                ipv4Routes.append(NEIPv4Route(destinationAddress: \"2.0.0.0\", subnetMask: \"254.0.0.0\"))\n                ipv4Routes.append(NEIPv4Route(destinationAddress: \"4.0.0.0\", subnetMask: \"252.0.0.0\"))\n                ipv4Routes.append(NEIPv4Route(destinationAddress: \"8.0.0.0\", subnetMask: \"248.0.0.0\"))\n                ipv4Routes.append(NEIPv4Route(destinationAddress: \"16.0.0.0\", subnetMask: \"240.0.0.0\"))\n                ipv4Routes.append(NEIPv4Route(destinationAddress: \"32.0.0.0\", subnetMask: \"224.0.0.0\"))\n                ipv4Routes.append(NEIPv4Route(destinationAddress: \"64.0.0.0\", subnetMask: \"192.0.0.0\"))\n                ipv4Routes.append(NEIPv4Route(destinationAddress: \"128.0.0.0\", subnetMask: \"128.0.0.0\"))\n                ipv4Routes.append(NEIPv4Route.default())\n            } else {\n                ipv4Routes.append(NEIPv4Route.default())\n            }\n\n            let inet4RouteExcludeAddressIterator = options.getInet4RouteExcludeAddress()!\n            while inet4RouteExcludeAddressIterator.hasNext() {\n                let ipv4RoutePrefix = inet4RouteExcludeAddressIterator.next()!\n                ipv4ExcludeRoutes.append(NEIPv4Route(destinationAddress: ipv4RoutePrefix.address(), subnetMask: ipv4RoutePrefix.mask()))\n            }\n            if excludeDefaultRoute, !ipv4Routes.isEmpty {\n                if !ipv4ExcludeRoutes.contains(where: { it in\n                    it.destinationAddress == \"0.0.0.0\" && it.destinationSubnetMask == \"255.255.255.254\"\n                }) {\n                    ipv4ExcludeRoutes.append(NEIPv4Route(destinationAddress: \"0.0.0.0\", subnetMask: \"255.255.255.254\"))\n                }\n            }\n            if excludeAPNs, !ipv4Routes.isEmpty {\n                if !ipv4ExcludeRoutes.contains(where: { it in\n                    it.destinationAddress == \"17.0.0.0\" && it.destinationSubnetMask == \"255.0.0.0\"\n                }) {\n                    ipv4ExcludeRoutes.append(NEIPv4Route(destinationAddress: \"17.0.0.0\", subnetMask: \"255.0.0.0\"))\n                }\n           }\n            ipv4Settings.includedRoutes = ipv4Routes\n            ipv4Settings.excludedRoutes = ipv4ExcludeRoutes\n            settings.ipv4Settings = ipv4Settings\n\n            var ipv6Address: [String] = []\n            var ipv6Prefixes: [NSNumber] = []\n            let ipv6AddressIterator = options.getInet6Address()!\n            while ipv6AddressIterator.hasNext() {\n                let ipv6Prefix = ipv6AddressIterator.next()!\n                ipv6Address.append(ipv6Prefix.address())\n                ipv6Prefixes.append(NSNumber(value: ipv6Prefix.prefix()))\n            }\n            let ipv6Settings = NEIPv6Settings(addresses: ipv6Address, networkPrefixLengths: ipv6Prefixes)\n            var ipv6Routes: [NEIPv6Route] = []\n            var ipv6ExcludeRoutes: [NEIPv6Route] = []\n\n            let inet6RouteAddressIterator = options.getInet6RouteAddress()!\n            if inet6RouteAddressIterator.hasNext() {\n                while inet6RouteAddressIterator.hasNext() {\n                    let ipv6RoutePrefix = inet6RouteAddressIterator.next()!\n                    ipv6Routes.append(NEIPv6Route(destinationAddress: ipv6RoutePrefix.address(), networkPrefixLength: NSNumber(value: ipv6RoutePrefix.prefix())))\n                }\n            } else if autoRouteUseSubRangesByDefault {\n                ipv6Routes.append(NEIPv6Route(destinationAddress: \"100::\", networkPrefixLength: 8))\n                ipv6Routes.append(NEIPv6Route(destinationAddress: \"200::\", networkPrefixLength: 7))\n                ipv6Routes.append(NEIPv6Route(destinationAddress: \"400::\", networkPrefixLength: 6))\n                ipv6Routes.append(NEIPv6Route(destinationAddress: \"800::\", networkPrefixLength: 5))\n                ipv6Routes.append(NEIPv6Route(destinationAddress: \"1000::\", networkPrefixLength: 4))\n                ipv6Routes.append(NEIPv6Route(destinationAddress: \"2000::\", networkPrefixLength: 3))\n                ipv6Routes.append(NEIPv6Route(destinationAddress: \"4000::\", networkPrefixLength: 2))\n                ipv6Routes.append(NEIPv6Route(destinationAddress: \"8000::\", networkPrefixLength: 1))\n                ipv6Routes.append(NEIPv6Route.default())\n            } else {\n                ipv6Routes.append(NEIPv6Route.default())\n            }\n\n            let inet6RouteExcludeAddressIterator = options.getInet6RouteExcludeAddress()!\n            while inet6RouteExcludeAddressIterator.hasNext() {\n                let ipv6RoutePrefix = inet6RouteExcludeAddressIterator.next()!\n                ipv6ExcludeRoutes.append(NEIPv6Route(destinationAddress: ipv6RoutePrefix.address(), networkPrefixLength: NSNumber(value: ipv6RoutePrefix.prefix())))\n            }\n            if excludeDefaultRoute, !ipv6Routes.isEmpty {\n                if !ipv6ExcludeRoutes.contains(where: { it in\n                    it.destinationAddress == \"::\" && it.destinationNetworkPrefixLength == 127\n                }) {\n                    ipv6ExcludeRoutes.append(NEIPv6Route(destinationAddress: \"::\", networkPrefixLength: 127))\n                }\n            }\n            ipv6Settings.includedRoutes = ipv6Routes\n            ipv6Settings.excludedRoutes = ipv6ExcludeRoutes\n            settings.ipv6Settings = ipv6Settings\n        }\n\n        if options.isHTTPProxyEnabled() {\n            let proxySettings = NEProxySettings()\n            let proxyServer = NEProxyServer(address: options.getHTTPProxyServer(), port: Int(options.getHTTPProxyServerPort()))\n            proxySettings.httpServer = proxyServer\n            proxySettings.httpsServer = proxyServer\n            if systemProxyEnabled {\n                proxySettings.httpEnabled = true\n                proxySettings.httpsEnabled = true\n            }\n\n            var bypassDomains: [String] = []\n            let bypassDomainIterator = options.getHTTPProxyBypassDomain()!\n            while bypassDomainIterator.hasNext() {\n                bypassDomains.append(bypassDomainIterator.next())\n            }\n\n            if excludeAPNs {\n                if !bypassDomains.contains(where: { it in\n                    it == \"push.apple.com\"\n                }) {\n                    bypassDomains.append(\"push.apple.com\")\n                }\n            }\n\n            if !bypassDomains.isEmpty {\n                proxySettings.exceptionList = bypassDomains\n            }\n\n            var matchDomains: [String] = []\n\n            let matchDomainIterator = options.getHTTPProxyMatchDomain()!\n\n            while matchDomainIterator.hasNext() {\n                matchDomains.append(matchDomainIterator.next())\n            }\n\n            if !matchDomains.isEmpty {\n                proxySettings.matchDomains = matchDomains\n            }\n            settings.proxySettings = proxySettings\n        }\n\n        networkSettings = settings\n        try await tunnel.setTunnelNetworkSettings(settings)\n\n        if let tunFd = tunnel.packetFlow.value(forKeyPath: \"socket.fileDescriptor\") as? Int32 {\n            ret0_.pointee = tunFd\n            return\n        }\n\n        let tunFdFromLoop = LibboxGetTunnelFileDescriptor()\n        if tunFdFromLoop != -1 {\n            ret0_.pointee = tunFdFromLoop\n        } else {\n            throw NSError(domain: \"missing file descriptor\", code: 0)\n        }\n    }\n\n    public func usePlatformAutoDetectControl() -> Bool {\n        false\n    }\n    public func findConnectionOwner(_ ipProtocol: Int32, sourceAddress: String?, sourcePort: Int32, destinationAddress: String?, destinationPort: Int32) throws -> LibboxConnectionOwner {\n        #if os(macOS)\n            if Variant.useSystemExtension {\n                guard let sourceAddress, let destinationAddress else {\n                    throw NSError(domain: \"findConnectionOwner\", code: 0, userInfo: [\n                        NSLocalizedDescriptionKey: \"Missing source or destination address\",\n                    ])\n                }\n                let owner = try RootHelperClient.shared.findConnectionOwner(\n                    ipProtocol: ipProtocol,\n                    sourceAddress: sourceAddress,\n                    sourcePort: sourcePort,\n                    destinationAddress: destinationAddress,\n                    destinationPort: destinationPort\n                )\n                let result = LibboxConnectionOwner()\n                result.userId = owner.userId\n                result.userName = owner.userName\n                result.processPath = owner.processPath\n                return result\n            }\n        #endif\n        throw NSError(domain: \"ExtensionPlatformInterface\", code: 0, userInfo: [NSLocalizedDescriptionKey: String(localized: \"Not implemented\")])\n    }\n\n    public func useProcFS() -> Bool {\n        false\n    }\n\n    public func writeLog(_ message: String?) {\n        guard let message else {\n            return\n        }\n        tunnel.writeMessage(message)\n    }\n\n    private var nwMonitor: NWPathMonitor?\n\n    public func startDefaultInterfaceMonitor(_ listener: LibboxInterfaceUpdateListenerProtocol?) throws {\n        return\n        guard let listener else {\n            return\n        }\n        let monitor = NWPathMonitor()\n        nwMonitor = monitor\n        let semaphore = DispatchSemaphore(value: 0)\n        monitor.pathUpdateHandler = { path in\n            self.onUpdateDefaultInterface(listener, path)\n            semaphore.signal()\n            monitor.pathUpdateHandler = { path in\n                self.onUpdateDefaultInterface(listener, path)\n            }\n        }\n        monitor.start(queue: DispatchQueue.global())\n        semaphore.wait()\n    }\n\n    private func onUpdateDefaultInterface(_ listener: LibboxInterfaceUpdateListenerProtocol, _ path: Network.NWPath) {\n        return\n        guard path.status != .unsatisfied,\n              let defaultInterface = path.availableInterfaces.first\n        else {\n            listener.updateDefaultInterface(\"\", interfaceIndex: -1, isExpensive: false, isConstrained: false)\n            return\n        }\n        listener.updateDefaultInterface(defaultInterface.name, interfaceIndex: Int32(defaultInterface.index), isExpensive: path.isExpensive, isConstrained: path.isConstrained)\n    }\n\n    public func closeDefaultInterfaceMonitor(_: LibboxInterfaceUpdateListenerProtocol?) throws {\n        nwMonitor?.cancel()\n        nwMonitor = nil\n    }\n\n    public func getInterfaces() throws -> LibboxNetworkInterfaceIteratorProtocol {\n        throw NSError(domain: \"not implemented\", code: 0)\n        guard let nwMonitor else {\n            throw NSError(domain: \"ExtensionPlatformInterface\", code: 0, userInfo: [NSLocalizedDescriptionKey: String(localized: \"NWMonitor not started\")])\n        }\n        let path = nwMonitor.currentPath\n        if path.status == .unsatisfied {\n            return networkInterfaceArray([])\n        }\n        var interfaces: [LibboxNetworkInterface] = []\n        for it in path.availableInterfaces {\n            let interface = LibboxNetworkInterface()\n            interface.name = it.name\n            interface.index = Int32(it.index)\n            switch it.type {\n            case .wifi:\n                interface.type = LibboxInterfaceTypeWIFI\n            case .cellular:\n                interface.type = LibboxInterfaceTypeCellular\n            case .wiredEthernet:\n                interface.type = LibboxInterfaceTypeEthernet\n            default:\n                interface.type = LibboxInterfaceTypeOther\n            }\n            interfaces.append(interface)\n        }\n        return networkInterfaceArray(interfaces)\n    }\n\n    class networkInterfaceArray: NSObject, LibboxNetworkInterfaceIteratorProtocol {\n        private var iterator: IndexingIterator<[LibboxNetworkInterface]>\n        init(_ array: [LibboxNetworkInterface]) {\n            iterator = array.makeIterator()\n        }\n\n        private var nextValue: LibboxNetworkInterface?\n\n        func hasNext() -> Bool {\n            nextValue = iterator.next()\n            return nextValue != nil\n        }\n\n        func next() -> LibboxNetworkInterface? {\n            nextValue\n        }\n    }\n\n    public func underNetworkExtension() -> Bool {\n        true\n    }\n\n    public func includeAllNetworks() -> Bool {\n        #if os(tvOS)\n            return false\n        #else\n            return false\n//            return tunnel.overridePreferences?.includeAllNetworks ?? false\n        #endif\n    }\n\n    public func clearDNSCache() {\n        guard let networkSettings else {\n            return\n        }\n        runBlocking {\n            self.tunnel.reasserting = true\n            defer { self.tunnel.reasserting = false }\n            await withCheckedContinuation { continuation in\n                self.tunnel.setTunnelNetworkSettings(nil) { _ in\n                    continuation.resume()\n                }\n            }\n            await withCheckedContinuation { continuation in\n                self.tunnel.setTunnelNetworkSettings(networkSettings) { _ in\n                    continuation.resume()\n                }\n            }\n        }\n    }\n\n    public func readWIFIState() -> LibboxWIFIState? {\n//        #if os(iOS)\n//            let network = runBlocking {\n//                await NEHotspotNetwork.fetchCurrent()\n//            }\n//            guard let network else {\n//                return nil\n//            }\n//            return LibboxWIFIState(network.ssid, wifiBSSID: network.bssid)!\n//        #elseif os(macOS)\n//            if Variant.useSystemExtension {\n//                return UserServiceClient.shared.readWIFIState()\n//            }\n//            guard let interface = CWWiFiClient.shared().interface() else {\n//                return nil\n//            }\n//            guard let ssid = interface.ssid() else {\n//                return nil\n//            }\n//            guard let bssid = interface.bssid() else {\n//                return nil\n//            }\n//            return LibboxWIFIState(ssid, wifiBSSID: bssid)!\n//        #else\n            return nil\n//        #endif\n    }\n\n    public func readWIFISSID() -> String? {\n//        #if os(iOS)\n//            return runBlocking {\n//                await NEHotspotNetwork.fetchCurrent()?.ssid\n//            }\n//        #elseif os(macOS)\n//            return CWWiFiClient.shared().interface()?.ssid()\n//        #else\n            return nil\n//        #endif\n    }\n\n//    public func serviceStop() throws {\n//        tunnel.stopService()\n//    }\n\n    public func serviceReload() throws {\n        try runBlocking { [self] in\n            try await tunnel.reloadService()\n        }\n    }\n\n    public func getSystemProxyStatus() throws -> LibboxSystemProxyStatus {\n        let status = LibboxSystemProxyStatus()\n        guard let networkSettings else {\n            return status\n        }\n        guard let proxySettings = networkSettings.proxySettings else {\n            return status\n        }\n        if proxySettings.httpServer == nil {\n            return status\n        }\n        status.available = true\n        status.enabled = proxySettings.httpEnabled\n        return status\n    }\n\n    public func setSystemProxyEnabled(_ isEnabled: Bool) throws {\n        guard let networkSettings else {\n            return\n        }\n        guard let proxySettings = networkSettings.proxySettings else {\n            return\n        }\n        if proxySettings.httpServer == nil {\n            return\n        }\n        if proxySettings.httpEnabled == isEnabled {\n            return\n        }\n        proxySettings.httpEnabled = isEnabled\n        proxySettings.httpsEnabled = isEnabled\n        networkSettings.proxySettings = proxySettings\n        try runBlocking {\n            try await self.tunnel.setTunnelNetworkSettings(networkSettings)\n        }\n    }\n\n    public func writeDebugMessage(_ message: String?) {\n        guard let message else {\n            return\n        }\n//        tunnel.writeMessage(message)\n    }\n\n    func reset() {\n        networkSettings = nil\n        nwMonitor?.cancel()\n        nwMonitor = nil\n    }\n\n    public func send(_ notification: LibboxNotification?) throws {\n        #if !os(tvOS)\n            guard let notification else {\n                return\n            }\n            #if os(macOS)\n                if Variant.useSystemExtension {\n                    try UserServiceClient.shared.sendNotification(notification)\n                    return\n                }\n            #endif\n//            let center = UNUserNotificationCenter.current()\n//            let content = UNMutableNotificationContent()\n//\n//            content.title = notification.title\n//            content.subtitle = notification.subtitle\n//            content.body = notification.body\n//            if !notification.openURL.isEmpty {\n//                content.userInfo[\"OPEN_URL\"] = notification.openURL\n//                content.categoryIdentifier = \"OPEN_URL\"\n//            }\n//            content.interruptionLevel = .active\n//            let request = UNNotificationRequest(identifier: notification.identifier, content: content, trigger: nil)\n//            try runBlocking {\n//                try await center.requestAuthorization(options: [.alert])\n//                try await center.add(request)\n//            }\n        #endif\n    }\n\n    public func localDNSTransport() -> (any LibboxLocalDNSTransportProtocol)? {\n        nil\n    }\n\n    public func systemCertificates() -> (any LibboxStringIteratorProtocol)? {\n        nil\n    }\n    public func autoDetectControl(_: Int32) throws {}\n\n}\n"
  },
  {
    "path": "ios/HiddifyPacketTunnel/SingBox/ExtensionProvider.swift",
    "content": "import Foundation\nimport HiddifyCore\nimport NetworkExtension\nimport os.log\n\nopen class ExtensionProvider: NEPacketTunnelProvider {\n    public static let errorFile = FilePath.workingDirectory.appendingPathComponent(\"network_extension_error.log\")\n    private let logger = Logger(subsystem: \"apple.hiddify.com.HiddifyPacketTunnel\", category: \"PacketTunnel\")\n    \n//    private var commandServer: LibboxCommandServer!\n    private var systemProxyAvailable = false\n    private var systemProxyEnabled = false\n    private var platformInterface: ExtensionPlatformInterface!\n    private var config: String!\n\n    override open func startTunnel(options: [String: NSObject]?) async throws {\n        // Clear previous logs\n        try? FileManager.default.removeItem(at: ExtensionProvider.errorFile)\n        try? FileManager.default.removeItem(at: FilePath.workingDirectory.appendingPathComponent(\"TestLog\"))\n        \n        do {\n            writeMessage(\"(packet-tunnel) starting\")\n            \n            // Extract options with better error handling\n            let disableMemoryLimit = false && (options?[\"DisableMemoryLimit\"] as? NSString as? String ?? \"NO\") == \"YES\" \n            let grpcServiceModePort = (options?[\"GrpcServiceModePort\"] as? NSNumber)?.intValue ?? 17079\n            \n            let config = options?[\"Config\"] as? NSString as? String ?? \"\"\n            \n            // guard let config = SingBox.setupConfig(config: config2) else {\n            //             writeFatalError(\"(packet-tunnel) error: config is invalid\")\n            //             return\n            // }\n//            self.config = config\n\n            do {\n                try FileManager.default.createDirectory(at: FilePath.workingDirectory, withIntermediateDirectories: true)\n            } catch {\n                writeFatalError(\"(packet-tunnel) error: create working directory: \\(error.localizedDescription)\")\n                return\n            }\n            \n            // Ensure directories exist\n            try createRequiredDirectories()\n            \n            // Log directory paths for debugging\n            let sharedDir = FilePath.sharedDirectory.relativePath\n            let workDir = FilePath.workingDirectory.relativePath\n            let cacheDir = FilePath.cacheDirectory.relativePath\n            if platformInterface == nil {\n                platformInterface = ExtensionPlatformInterface(self)\n            }\n            // Initialize mobile setup with error handling\n            var setupError: NSError?\n            let opts = MobileSetupOptions()\n            opts.basePath = sharedDir\n            opts.workingDir = workDir\n            opts.tempDir = cacheDir\n            opts.listen = \"127.0.0.1:\\(grpcServiceModePort)\"\n            opts.secret = \"\"\n            opts.debug = false\n            opts.mode = 4\n            opts.fixAndroidStack = false\n\n            MobileSetup(opts,\n                platformInterface,\n                &setupError\n            )\n            \n            if let setupError = setupError {\n                throw setupError\n            }\n            \n            \n            LibboxSetMemoryLimit(!disableMemoryLimit)\n            \n            writeMessage(\"(packet-tunnel) setup completed successfully\")\n            if (config==\"\"){\n                try await startService1(config)\n            }\n\n            \n        } catch {\n            logger.error(\"Tunnel setup failed: \\(error.localizedDescription)\")\n            writeFatalError(\"(packet-tunnel) setup failed: \\(error.localizedDescription)\")\n            throw error\n        }\n    }\n    \n    private func startService1(_ config: String) async throws {\n        writeMessage(\"Starting service\")\n        var error: NSError?\n//        \n        do {\n            try MobileStart(config, \"\", &error)\n            if let error = error {\n                throw error\n            }\n            writeMessage(\"(packet-tunnel) service started successfully\")\n        } catch {\n            writeFatalError(\"(packet-tunnel) error: start service: \\(error.localizedDescription)\")\n            throw error\n        }\n    }\n    \n    private func createRequiredDirectories() throws {\n        let directories = [\n            FilePath.workingDirectory,\n            FilePath.sharedDirectory,\n            FilePath.cacheDirectory\n        ]\n        \n        for directory in directories {\n            do {\n                try FileManager.default.createDirectory(\n                    at: directory,\n                    withIntermediateDirectories: true,\n                    attributes: nil\n                )\n            } catch {\n                logger.error(\"Failed to create directory at \\(directory.path): \\(error.localizedDescription)\")\n                throw error\n            }\n        }\n    }\n    \n    func writeMessage(_ message: String) {\n        logger.debug(\"\\(message)\")\n        writeError(message)\n    }\n    \n    func writeError(_ message: String) {\n        let messageWithNewline = \"[\\(Date())] \\(message)\\n\"\n        do {\n            if FileManager.default.fileExists(atPath: ExtensionProvider.errorFile.path) {\n                if let fileHandle = try? FileHandle(forWritingTo: ExtensionProvider.errorFile) {\n                    defer { fileHandle.closeFile() }\n                    fileHandle.seekToEndOfFile()\n                    if let data = messageWithNewline.data(using: .utf8) {\n                        fileHandle.write(data)\n                    }\n                }\n            } else {\n                try messageWithNewline.write(to: ExtensionProvider.errorFile, atomically: true, encoding: .utf8)\n            }\n        } catch {\n            logger.error(\"Failed to write to error file: \\(error.localizedDescription)\")\n        }\n    }\n    \n    public func writeFatalError(_ message: String) {\n        logger.fault(\"Fatal error: \\(message)\")\n        writeError(\"FATAL: \\(message)\")\n        cancelTunnelWithError(NSError(domain: \"ExtensionProvider\", code: 0, userInfo: [NSLocalizedDescriptionKey: message]))\n    }\n    \n    override open func stopTunnel(with reason: NEProviderStopReason) async {\n//        logger.debug(\"Stopping tunnel with reason: \\(reason)\")\n        writeMessage(\"(packet-tunnel) stopping, reason: \\(reason)\")\n        stopService()\n        \n//        // Allow time for cleanup\n//        try? await Task.sleep(nanoseconds: 100 * NSEC_PER_MSEC)\n//        \n//        if let server = commandServer {\n//            try? server.close()\n//            commandServer = nil\n//        }\n    }\n    \n    private func stopService() {\n        logger.debug(\"Stopping service\")\n        MobileClose(4)\n        if let platformInterface {\n            platformInterface.reset()\n        }\n    }\n    \n    func reloadService() async {\n        logger.debug(\"Reloading service\")\n        writeMessage(\"(packet-tunnel) reloading service\")\n//        reasserting = true\n//        defer { reasserting = false }\n//        \n//        stopService()\n//        do {\n//            guard let config = try? String(contentsOf: FilePath.configFile) else {\n//                writeFatalError(\"(packet-tunnel) error: cannot read config file\")\n//                return\n//            }\n//            try await startService(config)\n//        } catch {\n//            writeFatalError(\"(packet-tunnel) error: reload service: \\(error.localizedDescription)\")\n//        }\n    }\n    \n    override open func handleAppMessage(_ messageData: Data) async -> Data? {\n        logger.debug(\"Handling app message\")\n        return messageData\n    }\n    \n    override open func sleep() async {\n        logger.debug(\"Entering sleep mode\")\n//        MobilePause()\n        // Add any sleep mode handling if needed\n    }\n    \n    override open func wake() {\n        logger.debug(\"Waking from sleep\")\n        MobileWake()\n        // Add any wake handling if needed\n    }\n}\n\n// Extension to support error handling\nextension ExtensionProvider {\n    enum ExtensionError: Error {\n        case configurationMissing\n        case directoryCreationFailed\n        case serviceStartFailed\n        \n        var localizedDescription: String {\n            switch self {\n            case .configurationMissing:\n                return \"Configuration not provided\"\n            case .directoryCreationFailed:\n                return \"Failed to create required directories\"\n            case .serviceStartFailed:\n                return \"Failed to start the service\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "ios/HiddifyPacketTunnel/SingBox/SingBox.swift",
    "content": "//\n//  SingBox.swift\n//  SingBoxPacketTunnel\n//\n//  Created by GFWFighter on 7/25/1402 AP.\n//\n\nimport Foundation\n\nclass SingBox {\n    static func setupConfig(config: String, mtu: Int = 9000) -> String? {\n        NSLog(\"H?B1\")\n        guard\n            let config = config.data(using: .utf8),\n            var json = try? JSONSerialization\n                .jsonObject(\n                    with: config,\n                    options: [.mutableLeaves, .mutableContainers]\n                ) as? [String:Any]\n        else {\n            return nil\n        }\n        /*json[\"log\"] = [\n            \"disabled\": false,\n            \"level\": \"info\",\n            \"output\": \"log\",\n            \"timestamp\": true\n        ] as [String:Any]\n        json[\"experimental\"] = [\n            \"clash_api\": [\n                \"external_controller\": \"127.0.0.1:10864\"\n            ]\n        ]\n        json[\"inbounds\"] = [\n            [\n                \"type\": \"tun\",\n                \"inet4_address\": \"172.19.0.1/30\",\n                \"auto_route\": true,\n                \"mtu\": mtu,\n                \"sniff\": true\n            ] as [String:Any]\n        ]\n        var routing = (json[\"route\"] as? [String:Any]) ?? [\n            \"rules\": [Any](),\n            \"auto_detect_interface\": true,\n            \"final\": (json[\"inbounds\"] as? [[String:Any]])?.first?[\"tag\"] ?? \"proxy\"\n        ]\n        routing[\"geoip\"] = [\n            \"path\": FilePath.assetsDirectory.appendingPathComponent(\"geoip.db\"),\n        ]\n        routing[\"geosite\"] = [\n            \"path\": FilePath.assetsDirectory.appendingPathComponent(\"geosite.db\"),\n        ]\n        json[\"route\"] = routing*/\n        guard let data = try? JSONSerialization.data(withJSONObject: json) else {\n            return nil\n        }\n        return String(data: data, encoding: .utf8)\n    }\n}\n"
  },
  {
    "path": "ios/HiddifyPacketTunnel/TrafficReader.swift",
    "content": "//\n//  TrafficReader.swift\n//  SingBoxPacketTunnel\n//\n//  Created by GFWFighter on 7/25/1402 AP.\n//\n\nimport Foundation\n\nstruct TrafficReaderUpdate: Codable {\n    let up: Int64\n    let down: Int64\n}\n\n\nclass TrafficReader {\n    private var task: URLSessionWebSocketTask!\n    private let callback: (TrafficReaderUpdate) -> ()\n    \n    init(onUpdate: @escaping (TrafficReaderUpdate) -> ()) {\n        NSLog(\"H?D2\")\n        self.callback = onUpdate\n        Task(priority: .background) { [weak self] () in\n            await self?.setup()\n        }\n    }\n    \n    private func setup() async {\n        NSLog(\"H?D1\")\n        try? await Task.sleep(nanoseconds: 5_000_000_000)\n        //return\n        while true {\n            do {\n                let (_, response) = try await URLSession.shared.data(from: URL(string: \"http://127.0.0.1:10864\")!)\n                let code = (response as? HTTPURLResponse)?.statusCode ?? -1\n                if code >= 200 && code < 300 {\n                    break\n                }\n            } catch {\n                // pass\n            }\n            try? await Task.sleep(nanoseconds: 5_000_000)\n        }\n        let task = URLSession.shared.webSocketTask(with: URL(string: \"ws://127.0.0.1:10864/traffic\")!)\n        self.task = task\n        read()\n        task.resume()\n    }\n    \n    private func read() {\n        NSLog(\"H?D3\")\n        task.receive { [weak self] result in\n            switch result {\n            case .failure(_):\n                break\n            case .success(let message):\n                switch message {\n                case .string(let message):\n                    guard let data = message.data(using: .utf8) else {\n                        break\n                    }\n                    guard let response = try? JSONDecoder().decode(TrafficReaderUpdate.self, from: data) else {\n                        break\n                    }\n                    self?.callback(response)\n                default:\n                    break\n                }\n                self?.read()\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Local Packages/Package.swift",
    "content": "// swift-tools-version: 5.4\n// The swift-tools-version declares the minimum version of Swift required to build this package.\n\nimport PackageDescription\n\nlet package = Package(\n     name: \"Hiddify Packages\",\n     platforms: [\n        // Minimum platform version\n         .iOS(.v13)\n     ],\n     products: [\n         .library(\n             name: \"HiddifyCore\",\n             targets: [\"HiddifyCore\"]),\n     ],\n     dependencies: [\n         // No dependencies\n     ],\n     targets: [\n        .binaryTarget(\n            name: \"HiddifyCore\",\n            path: \"../Frameworks/HiddifyCore.xcframework\"\n        )\n     ]\n )\n"
  },
  {
    "path": "ios/Podfile",
    "content": "# Uncomment this line to define a global platform for your project\nplatform :ios, '15.5'\n\n# CocoaPods analytics sends network stats synchronously affecting flutter build latency.\nENV['COCOAPODS_DISABLE_STATS'] = 'true'\n\nproject 'Runner', {\n  'Debug' => :debug,\n  'Profile' => :release,\n  'Release' => :release,\n}\n\ndef flutter_root\n  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)\n  unless File.exist?(generated_xcode_build_settings_path)\n    raise \"#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first\"\n  end\n\n  File.foreach(generated_xcode_build_settings_path) do |line|\n    matches = line.match(/FLUTTER_ROOT\\=(.*)/)\n    return matches[1].strip if matches\n  end\n  raise \"FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get\"\nend\n\nrequire File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)\n\nflutter_ios_podfile_setup\n\ntarget 'Runner' do\n  use_frameworks!\n  use_modular_headers!\n\n  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))\n  pod 'EasyPermissionX/Camera'\n\n  target 'RunnerTests' do\n    inherit! :search_paths\n  end\nend\n\npost_install do |installer|\n  installer.pods_project.targets.each do |target|\n    flutter_additional_ios_build_settings(target)\n    target.build_configurations.each do |config|\n      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'\n    end\n  end\nend\n"
  },
  {
    "path": "ios/Runner/AppDelegate.swift",
    "content": "import UIKit\nimport Flutter\nimport HiddifyCore\nimport Sentry\n@main\n@objc class AppDelegate: FlutterAppDelegate {\n    \n    override func application(\n        _ application: UIApplication,\n        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n    ) -> Bool {\n        setupFileManager()\n        registerHandlers()\n        GeneratedPluginRegistrant.register(with: self)\n        return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n    }\n    \n    func setupFileManager() {\n        try? FileManager.default.createDirectory(at: FilePath.workingDirectory, withIntermediateDirectories: true)\n        FileManager.default.changeCurrentDirectoryPath(FilePath.sharedDirectory.path)\n    }\n    \n    func registerHandlers() {\n        MethodHandler.register(with: self.registrar(forPlugin: MethodHandler.name)!)\n        PlatformMethodHandler.register(with: self.registrar(forPlugin: PlatformMethodHandler.name)!)\n        FileMethodHandler.register(with: self.registrar(forPlugin: FileMethodHandler.name)!)\n        StatusEventHandler.register(with: self.registrar(forPlugin: StatusEventHandler.name)!)\n        AlertsEventHandler.register(with: self.registrar(forPlugin: AlertsEventHandler.name)!)\n//        LogsEventHandler.register(with: self.registrar(forPlugin: LogsEventHandler.name)!)\n//        GroupsEventHandler.register(with: self.registrar(forPlugin: GroupsEventHandler.name)!)\n//        ActiveGroupsEventHandler.register(with: self.registrar(forPlugin: ActiveGroupsEventHandler.name)!)\n//        StatsEventHandler.register(with: self.registrar(forPlugin: StatsEventHandler.name)!)\n    }\n}\n\n"
  },
  {
    "path": "ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"filename\" : \"app-icon-1024.png\",\n      \"idiom\" : \"universal\",\n      \"platform\" : \"ios\",\n      \"size\" : \"1024x1024\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"filename\" : \"background.png\",\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"filename\" : \"LaunchImage.png\",\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"filename\" : \"LaunchImage@2x.png\",\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"filename\" : \"LaunchImage@3x.png\",\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md",
    "content": "# Launch Screen Assets\n\nYou can customize the launch screen with your own desired assets by replacing the image files in this directory.\n\nYou can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images."
  },
  {
    "path": "ios/Runner/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"12121\" systemVersion=\"16G29\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" colorMatched=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"12089\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Ydg-fD-yQy\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xbc-2k-c8Z\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <imageView clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" image=\"LaunchBackground\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"tWc-Dq-wcI\"/>\n                            <imageView opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" image=\"LaunchImage\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YRO-k0-Ey4\"></imageView>\n                        </subviews>\n                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"leading\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"leading\" id=\"3T2-ad-Qdv\"/>\n                            <constraint firstItem=\"tWc-Dq-wcI\" firstAttribute=\"bottom\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"bottom\" id=\"RPx-PI-7Xg\"/>\n                            <constraint firstItem=\"tWc-Dq-wcI\" firstAttribute=\"top\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"top\" id=\"SdS-ul-q2q\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"tWc-Dq-wcI\" secondAttribute=\"trailing\" id=\"Swv-Gf-Rwn\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"YRO-k0-Ey4\" secondAttribute=\"trailing\" id=\"TQA-XW-tRk\"/>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"bottom\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"bottom\" id=\"duK-uY-Gun\"/>\n                            <constraint firstItem=\"tWc-Dq-wcI\" firstAttribute=\"leading\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"leading\" id=\"kV7-tw-vXt\"/>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"top\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"top\" id=\"xPn-NY-SIU\"/>\n                        </constraints>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <image name=\"LaunchImage\" width=\"1024\" height=\"1024\"/>\n        <image name=\"LaunchBackground\" width=\"1\" height=\"1\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "ios/Runner/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"22154\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" colorMatched=\"YES\" initialViewController=\"BYZ-38-t0r\">\n    <device id=\"retina6_12\" orientation=\"portrait\" appearance=\"light\"/>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"22130\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <scenes>\n        <!--Flutter View Controller-->\n        <scene sceneID=\"tne-QT-ifu\">\n            <objects>\n                <viewController id=\"BYZ-38-t0r\" customClass=\"FlutterViewController\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"y3c-jy-aDJ\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"wfy-db-euE\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"393\" height=\"852\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"-26\" y=\"-77\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "ios/Runner/Extensions/Bundle+Properties.swift",
    "content": "//\n//  Bundle+Properties.swift\n//  Runner\n//\n//  Created by Hiddify on 12/26/23.\n//\n\nimport Foundation\n\nextension Bundle {\n    var serviceIdentifier: String {\n        (infoDictionary?[\"SERVICE_IDENTIFIER\"] as? String)!\n    }\n    \n    var baseBundleIdentifier: String {\n        (infoDictionary?[\"BASE_BUNDLE_IDENTIFIER\"] as? String)!\n    }\n}\n"
  },
  {
    "path": "ios/Runner/Handlers/ActiveGroupsEventHandler.swift",
    "content": "import Foundation\nimport Combine\nimport HiddifyCore\n\npublic class ActiveGroupsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler {\n    \n    static let name = \"\\(Bundle.main.serviceIdentifier)/active-groups\"\n    private var commandClient: CommandClient?\n    private var channel: FlutterEventChannel?\n    private var events: FlutterEventSink?\n    private var cancellable: AnyCancellable?\n    \n    public static func register(with registrar: FlutterPluginRegistrar) {\n        let instance = ActiveGroupsEventHandler()\n        instance.channel = FlutterEventChannel(name: Self.name,\n                                               binaryMessenger: registrar.messenger())\n        instance.channel?.setStreamHandler(instance)\n    }\n    \n    public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {\n        FileManager.default.changeCurrentDirectoryPath(FilePath.sharedDirectory.path)\n        self.events = events\n        commandClient = CommandClient(.groupsInfoOnly)\n        commandClient?.connect()\n        cancellable =  commandClient?.$groups.sink{ [self] sbGroups in\n            self.writeGroups(sbGroups)\n        }\n        return nil\n    }\n    \n    public func onCancel(withArguments arguments: Any?) -> FlutterError? {\n        commandClient?.disconnect()\n        cancellable?.cancel()\n        events = nil\n        return nil\n    }\n    \n    func writeGroups(_ sbGroups: [SBGroup]?) {\n        guard let sbGroups else {return}\n        if\n            let groups = try? JSONEncoder().encode(sbGroups),\n            let groups = String(data: groups, encoding: .utf8)\n        {\n            DispatchQueue.main.async { [events = self.events, groups] () in\n                events?(groups)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Runner/Handlers/AlertsEventHandler.swift",
    "content": "//\n//  AlertEventHandler.swift\n//  Runner\n//\n//  Created by GFWFighter on 10/24/23.\n//\n\nimport Foundation\nimport Combine\n\npublic class AlertsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler {\n    static let name = \"\\(Bundle.main.serviceIdentifier)/service.alerts\"\n    \n    private var channel: FlutterEventChannel?\n    \n    private var cancellable: AnyCancellable?\n    \n    public static func register(with registrar: FlutterPluginRegistrar) {\n        let instance = AlertsEventHandler()\n        instance.channel = FlutterEventChannel(name: Self.name, binaryMessenger: registrar.messenger(), codec: FlutterJSONMethodCodec())\n        instance.channel?.setStreamHandler(instance)\n    }\n    \n    public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {\n        cancellable = VPNManager.shared.$alert.sink { [events] alert in\n            var data = [\n                \"status\": \"Stopped\",\n                \"alert\": alert.alert?.rawValue,\n                \"message\": alert.message,\n            ]\n            for key in data.keys {\n                if data[key] == nil {\n                    data.removeValue(forKey: key)\n                }\n            }\n            events(data)\n        }\n        return nil\n    }\n    \n    public func onCancel(withArguments arguments: Any?) -> FlutterError? {\n        cancellable?.cancel()\n        return nil\n    }\n}\n"
  },
  {
    "path": "ios/Runner/Handlers/FileMethodHandler.swift",
    "content": "//\n//  FileMethodHandler.swift\n//  Runner\n//\n//  Created by GFWFighter on 10/24/23.\n//\n\nimport Foundation\n\npublic class FileMethodHandler: NSObject, FlutterPlugin {\n        \n    public static let name = \"\\(Bundle.main.serviceIdentifier)/files.method\"\n    \n    public static func register(with registrar: FlutterPluginRegistrar) {\n        let channel = FlutterMethodChannel(name: Self.name, binaryMessenger: registrar.messenger())\n        let instance = FileMethodHandler()\n        registrar.addMethodCallDelegate(instance, channel: channel)\n        instance.channel = channel\n    }\n    \n    private var channel: FlutterMethodChannel?\n    \n    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {\n        switch call.method {\n        case \"get_paths\":\n            result([\n                \"working\": FilePath.workingDirectory.path,\n                \"temp\": FilePath.cacheDirectory.path,\n                \"base\": FilePath.sharedDirectory.path\n            ])\n        default:\n            result(FlutterMethodNotImplemented)\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Runner/Handlers/GroupsEventHandler.swift",
    "content": "import Foundation\nimport Combine\nimport HiddifyCore\n\npublic class GroupsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler{\n    \n    static let name = \"\\(Bundle.main.serviceIdentifier)/groups\"\n    \n    private var commandClient: CommandClient?\n    private var channel: FlutterEventChannel?\n    private var events: FlutterEventSink?\n    private var cancellable: AnyCancellable?\n    \n    public static func register(with registrar: FlutterPluginRegistrar) {\n        let instance = GroupsEventHandler()\n        instance.channel = FlutterEventChannel(name: Self.name,\n                                               binaryMessenger: registrar.messenger())\n        instance.channel?.setStreamHandler(instance)\n    }\n    \n    public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {\n        FileManager.default.changeCurrentDirectoryPath(FilePath.sharedDirectory.path)\n        self.events = events\n        commandClient = CommandClient(.groups)\n        commandClient?.connect()\n        cancellable = commandClient?.$groups.sink{ [self] groups in\n            self.writeGroups(groups)\n        }\n        return nil\n    }\n    \n    public func onCancel(withArguments arguments: Any?) -> FlutterError? {\n        commandClient?.disconnect()\n        cancellable?.cancel()\n        events = nil\n        return nil\n    }\n    \n    func writeGroups(_ sbGroups: [SBGroup]?) {\n        guard let sbGroups else {return}\n        if\n            let groups = try? JSONEncoder().encode(sbGroups),\n            let groups = String(data: groups, encoding: .utf8)\n        {\n            DispatchQueue.main.async { [events = self.events, groups] in\n                events?(groups)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Runner/Handlers/LogsEventHandler.swift",
    "content": "import Foundation\nimport Combine\nimport HiddifyCore\n\nclass LogsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler {\n    static let name = \"\\(Bundle.main.serviceIdentifier)/service.logs\"\n    \n    private var commandClient: CommandClient?\n    private var events: FlutterEventSink?\n    private var channel: FlutterEventChannel?\n    private var cancellable: AnyCancellable?\n\n    public static func register(with registrar: FlutterPluginRegistrar) {\n          let instance = LogsEventHandler()\n          instance.channel = FlutterEventChannel(name: Self.name,\n                                                 binaryMessenger: registrar.messenger())\n          instance.channel?.setStreamHandler(instance)\n    }\n\n    public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {\n        FileManager.default.changeCurrentDirectoryPath(FilePath.sharedDirectory.path)\n        self.events = events\n        commandClient = CommandClient(.log)\n        commandClient?.connect()\n        cancellable =  commandClient?.$logList.sink{ [self] logs in\n            events(logs)\n        }\n        return nil\n    }\n\n    public func onCancel(withArguments arguments: Any?) -> FlutterError? {\n        commandClient?.disconnect()\n        cancellable?.cancel()\n        events = nil\n        return nil\n    }\n}\n\n/*\nextension LogsEventHandler {\n    public func clearLog() {}\n    public func connected() {}\n    public func disconnected(_ message: String?) {}\n    public func initializeClashMode(_ modeList: LibboxStringIteratorProtocol?, currentMode: String?) {}\n    public func updateClashMode(_ newMode: String?) {}\n    public func writeGroups(_ message: LibboxOutboundGroupIteratorProtocol?) {}\n    public func writeStatus(_ message: LibboxStatusMessage?) {}\n}\n*/\n"
  },
  {
    "path": "ios/Runner/Handlers/MethodHandler.swift",
    "content": "//\n//  MethodHandler.swift\n//  Runner\n//\n//  Created by GFWFighter on 10/23/23.\n//\n\nimport Flutter\nimport Combine\nimport HiddifyCore\n\npublic class MethodHandler: NSObject, FlutterPlugin {\n    \n    private var cancelBag: Set<AnyCancellable> = []\n    \n    public static let name = \"\\(Bundle.main.serviceIdentifier)/method\"\n    \n    public static func register(with registrar: FlutterPluginRegistrar) {\n        let channel = FlutterMethodChannel(name: Self.name, binaryMessenger: registrar.messenger())\n        let instance = MethodHandler()\n        registrar.addMethodCallDelegate(instance, channel: channel)\n        instance.channel = channel\n    }\n    \n    private var channel: FlutterMethodChannel?\n    \n    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {\n        @Sendable func mainResult(_ res: Any?) async -> Void {\n            await MainActor.run {\n                result(res)\n            }\n        }\n        \n        switch call.method {\n        case \"get_grpc_server_public_key\":\n            result(\"\")\n        case \"add_grpc_client_public_key\":\n            result(\"\")\n        case \"parse_config\":\n            guard\n                let args = call.arguments as? [String:Any?],\n                let path = args[\"path\"] as? String,\n                let tempPath = args[\"tempPath\"] as? String,\n                let debug = (args[\"debug\"] as? NSNumber)?.boolValue\n            else {\n                result(FlutterError(code: \"INVALID_ARGS\", message: nil, details: nil))\n                return\n            }\n            var error: NSError?\n            //MobileParse(path, tempPath, debug, &error)\n            if let error {\n                result(FlutterError(code: String(error.code), message: error.description, details: nil))\n                return\n            }\n            result(\"\")\n        case \"change_hiddify_options\":\n            guard let options = call.arguments as? String else {\n                result(FlutterError(code: \"INVALID_ARGS\", message: nil, details: nil))\n                return\n            }\n            VPNConfig.shared.configOptions = options\n            result(true)\n        case \"setup\":\n                Task {\n                    guard\n                        let args = call.arguments as? [String: Any?],\n                        let baseDir = args[\"baseDir\"] as? String,\n                        let workingDir = args[\"workingDir\"] as? String,\n                        let tempDir = args[\"tempDir\"] as? String,\n                        let mode = args[\"mode\"] as? Int,\n                        let grpcPort = args[\"grpcPort\"] as? Int\n                    else {\n                        result(FlutterError(code: \"INVALID_ARGS\", message: nil, details: nil))\n                        return\n                    }\n                    VPNConfig.shared.baseDir=baseDir\n                    VPNConfig.shared.workingDir=workingDir\n                    VPNConfig.shared.tempDir=tempDir\n                    var error: NSError?\n                    let opts = MobileSetupOptions()\n                    opts.basePath = baseDir\n                    opts.workingDir = workingDir\n                    opts.tempDir = tempDir\n                    opts.listen = \"127.0.0.1:\\(grpcPort)\"\n                    opts.secret = \"\"\n                    opts.debug = false\n                    opts.mode = 4\n                    opts.fixAndroidStack = false\n                    MobileSetup(opts,\n                        nil,\n                        &error\n                    )\n                    \n                    if let error {\n                        result(FlutterError(code: String(error.code), message: error.localizedDescription, details: nil))\n                        return\n                    }\n                    do {\n                        try await VPNManager.shared.setup()\n                    } catch {\n                        result(FlutterError(code: \"SETUP\", message: error.localizedDescription, details: nil))\n                        return\n                    }\n                    result(true)\n                }\n        case \"start\":\n            Task {\n                guard\n                    let args = call.arguments as? [String:Any?],\n                    let path = args[\"path\"] as? String,\n                    let name = args[\"name\"] as? String,\n                    let grpcPort=args[\"grpcPort\"] as? Int\n                else {\n                    await mainResult(FlutterError(code: \"INVALID_ARGS\", message: nil, details: nil))\n                    return\n                }\n                VPNConfig.shared.activeConfigPath = path\n                VPNConfig.shared.activeProfileName = name\n                VPNConfig.shared.grpcServiceModePort=grpcPort\n                \n                var error: NSError?\n                //let configstr=MobileBuildConfig(path,&error) as String\n                if let error {\n                    await mainResult(FlutterError(code: String(error.code), message: error.description, details: nil))\n                    return\n                }\n                do {\n                    try await VPNManager.shared.setup()\n                    try await VPNManager.shared.connect(with: path, grpcServiceModePort: grpcPort, disableMemoryLimit: VPNConfig.shared.disableMemoryLimit)\n                } catch {\n                    await mainResult(FlutterError(code: \"SETUP_CONNECTION\", message: error.localizedDescription, details: nil))\n                    return\n                }\n                await mainResult(true)\n            }\n//        case \"restart\":\n//            Task { [unowned self] in\n//                guard\n//                    let args = call.arguments as? [String:Any?],\n//                    let path = args[\"path\"] as? String,\n//                    let name = args[\"name\"] as? String,\n//                    let grpcPort=args[\"grpcPort\"] as? Int\n//                else {\n//                    await mainResult(FlutterError(code: \"INVALID_ARGS\", message: nil, details: nil))\n//                    return\n//                }\n//                VPNConfig.shared.activeConfigPath = path\n//                VPNConfig.shared.activeProfileName = name\n//                VPNConfig.shared.grpcServiceModePort=grpcPort\n//                \n//                \n//                VPNManager.shared.disconnect()\n//                await waitForStop().value\n//                var error: NSError?\n//                do {\n//                    try await VPNManager.shared.setup()\n//                    try await VPNManager.shared.connect(with: path, disableMemoryLimit: VPNConfig.shared.disableMemoryLimit)\n//                } catch {\n//                    await mainResult(FlutterError(code: \"SETUP_CONNECTION\", message: error.localizedDescription, details: nil))\n//                    return\n//                }\n//                await mainResult(true)\n//            }\n        case \"stop\":\n            VPNManager.shared.disconnect()\n            result(true)\n        case \"reset\":\n            VPNManager.shared.reset()\n            result(true)\n        case \"url_test\":\n            guard\n                let args = call.arguments as? [String:Any?]\n            else {\n                result(FlutterError(code: \"INVALID_ARGS\", message: nil, details: nil))\n                return\n            }\n            let group = args[\"groupTag\"] as? String\n            FileManager.default.changeCurrentDirectoryPath(FilePath.sharedDirectory.path)\n            do {\n                try LibboxNewStandaloneCommandClient()?.urlTest(group)\n            } catch {\n                result(FlutterError(code: \"URL_TEST\", message: error.localizedDescription, details: nil))\n                return\n            }\n            result(true)\n        case \"select_outbound\":\n            guard\n                let args = call.arguments as? [String:Any?],\n                let group = args[\"groupTag\"] as? String,\n                let outbound = args[\"outboundTag\"] as? String\n            else {\n                result(FlutterError(code: \"INVALID_ARGS\", message: nil, details: nil))\n                return\n            }\n            FileManager.default.changeCurrentDirectoryPath(FilePath.sharedDirectory.path)\n            do {\n                try LibboxNewStandaloneCommandClient()?.selectOutbound(group, outboundTag: outbound)\n            } catch {\n                result(FlutterError(code: \"SELECT_OUTBOUND\", message: error.localizedDescription, details: nil))\n                return\n            }\n            result(true)\n        case \"generate_config\":\n            guard\n                let args = call.arguments as? [String:Any?],\n                let path = args[\"path\"] as? String\n            else {\n                result(FlutterError(code: \"INVALID_ARGS\", message: nil, details: nil))\n                return\n            }\n            var error: NSError?\n//            let config = MobileBuildConfig(path, VPNConfig.shared.configOptions, &error)\n//            if let error {\n//                result(FlutterError(code: \"BUILD_CONFIG\", message: error.localizedDescription, details: nil))\n//                return\n//            }\n//            result(config)\n        case \"generate_warp_config\":\n            guard let args = call.arguments as? [String: Any],\n                  let licenseKey = args[\"license-key\"] as? String,\n                  let accountId = args[\"previous-account-id\"] as? String,\n                  let accessToken = args[\"previous-access-token\"] as? String else {\n                result(FlutterError(code: \"INVALID_ARGS\", message: nil, details: nil))\n                return\n            }\n//            let warpConfig = MobileGenerateWarpConfig(licenseKey, accountId, accessToken, nil)\n//            result(warpConfig)\n        default:\n            result(FlutterMethodNotImplemented)\n        }\n    }\n    \n    private func waitForStop() -> Future<Void, Never> {\n        return Future { promise in\n            var cancellable: AnyCancellable? = nil\n            cancellable = VPNManager.shared.$state\n                .filter { $0 == .disconnected }\n                .first()\n                .delay(for: 0.5, scheduler: RunLoop.current)\n                .sink(receiveValue: { _ in\n                    promise(.success(()))\n                    cancellable?.cancel()\n                })\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Runner/Handlers/PlatformMethodHandler.swift",
    "content": "//\n//  PlatformMethodHandler.swift\n//  Runner\n//\n//  Created by Hiddify on 12/27/23.\n//\n\nimport Flutter\nimport Combine\nimport HiddifyCore\n\npublic class PlatformMethodHandler: NSObject, FlutterPlugin {\n        \n    public static let name = \"\\(Bundle.main.serviceIdentifier)/platform\"\n    \n    public static func register(with registrar: FlutterPluginRegistrar) {\n        let channel = FlutterMethodChannel(name: Self.name, binaryMessenger: registrar.messenger())\n        let instance = PlatformMethodHandler()\n        registrar.addMethodCallDelegate(instance, channel: channel)\n        instance.channel = channel\n    }\n    \n    private var channel: FlutterMethodChannel?\n    \n    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {\n        switch call.method {\n        case \"get_paths\":\n            result(getPaths(args: call.arguments) as NSDictionary)\n        default:\n            result(FlutterMethodNotImplemented)\n        }\n    }\n    \n    public func getPaths(args: Any?) -> [String:String] {\n        return [\n            \"base\": FilePath.sharedDirectory.path,\n            \"working\": FilePath.workingDirectory.path,\n            \"temp\": FilePath.cacheDirectory.path\n        ]\n    }\n}\n"
  },
  {
    "path": "ios/Runner/Handlers/StatsEventHandler.swift",
    "content": "import Foundation\nimport Flutter\nimport Combine\nimport HiddifyCore\n\npublic class StatsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler {\n    \n    static let name = \"\\(Bundle.main.serviceIdentifier)/stats\"\n    \n    private var commandClient: CommandClient?\n    private var channel: FlutterEventChannel?\n    private var events: FlutterEventSink?\n    private var cancellable: AnyCancellable?\n    \n    public static func register(with registrar: FlutterPluginRegistrar) {\n        let instance = StatsEventHandler()\n        instance.channel = FlutterEventChannel(name: Self.name,\n                                               binaryMessenger: registrar.messenger(),\n                                               codec: FlutterJSONMethodCodec())\n        instance.channel?.setStreamHandler(instance)\n    }\n    \n    public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {\n        FileManager.default.changeCurrentDirectoryPath(FilePath.sharedDirectory.path)\n        self.events = events\n        commandClient = CommandClient(.status)\n        commandClient?.connect()\n        cancellable =  commandClient?.$status.sink{ [self] status in\n            self.writeStatus(status)\n        }\n        return nil\n    }\n    \n    public func onCancel(withArguments arguments: Any?) -> FlutterError? {\n        commandClient?.disconnect()\n        cancellable?.cancel()\n        events = nil\n        return nil\n    }\n    \n    func writeStatus(_ message: LibboxStatusMessage?) {\n        guard let message else { return }\n        \n        let data = [\n            \"connections-in\": message.connectionsIn,\n            \"connections-out\": message.connectionsOut,\n            \"uplink\": message.uplink,\n            \"downlink\": message.downlink,\n            \"uplink-total\": message.uplinkTotal,\n            \"downlink-total\": message.downlinkTotal\n        ] as [String:Any]\n        events?(data)\n    }\n}\n"
  },
  {
    "path": "ios/Runner/Handlers/StatusEventHandler.swift",
    "content": "//\n//  StatusEventHandler.swift\n//  Runner\n//\n//  Created by GFWFighter on 10/24/23.\n//\n\nimport Foundation\nimport Combine\n\npublic class StatusEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler {\n    static let name = \"\\(Bundle.main.serviceIdentifier)/service.status\"\n    \n    private var channel: FlutterEventChannel?\n    \n    private var cancellable: AnyCancellable?\n    \n    public static func register(with registrar: FlutterPluginRegistrar) {\n        let instance = StatusEventHandler()\n        instance.channel = FlutterEventChannel(name: Self.name, binaryMessenger: registrar.messenger(), codec: FlutterJSONMethodCodec())\n        instance.channel?.setStreamHandler(instance)\n    }\n    \n    public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {\n        cancellable = VPNManager.shared.$state.sink { [events] status in\n            switch status {\n            case .reasserting, .connecting:\n                events([\"status\": \"Starting\"])\n            case .connected:\n                events([\"status\": \"Started\"])\n            case .disconnecting:\n                events([\"status\": \"Stopping\"])\n            case .disconnected, .invalid:\n                events([\"status\": \"Stopped\"])\n            @unknown default:\n                events([\"status\": \"Stopped\"])\n            }\n        }\n        return nil\n    }\n    \n    public func onCancel(withArguments arguments: Any?) -> FlutterError? {\n        cancellable?.cancel()\n        return nil\n    }\n}\n"
  },
  {
    "path": "ios/Runner/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BASE_BUNDLE_IDENTIFIER</key>\n\t<string>$(BASE_BUNDLE_IDENTIFIER)</string>\n\t<key>CADisableMinimumFrameDurationOnPhone</key>\n\t<true/>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>Hiddify</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(FLUTTER_BUILD_NAME)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleURLTypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>hiddify</string>\n\t\t\t\t<string>v2ray</string>\n\t\t\t\t<string>v2rayn</string>\n\t\t\t\t<string>v2rayng</string>\n\t\t\t\t<string>clash</string>\n\t\t\t\t<string>clashmeta</string>\n\t\t\t\t<string>sing-box</string>\n\t\t\t</array>\n\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>Editor</string>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>com.hiddify.ios</string>\n\t\t</dict>\n\t</array>\n\t<key>FlutterDeepLinkingEnabled</key>\n\t<true/>\n\t<key>CFBundleVersion</key>\n\t<string>$(FLUTTER_BUILD_NUMBER)</string>\n\t<key>EXAppExtensionAttributes</key>\n\t<dict>\n\t\t<key>EXExtensionPointIdentifier</key>\n\t\t<string>com.apple.appintents-extension</string>\n\t</dict>\n\t<key>ITSAppUsesNonExemptEncryption</key>\n\t<false/>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSCameraUsageDescription</key>\n\t<string>This app needs camera access to scan QR codes</string>\n\t<key>NSPhotoLibraryUsageDescription</key>\n\t<string>This app needs photos access to get QR code from photo library</string>\n\t<key>SERVICE_IDENTIFIER</key>\n\t<string>$(SERVICE_IDENTIFIER)</string>\n\t<key>UIApplicationSupportsIndirectInputEvents</key>\n\t<true/>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UIRequiresFullScreen</key>\n\t<true/>\n\t<key>UIStatusBarHidden</key>\n\t<false/>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t</array>\n\t<key>UIViewControllerBasedStatusBarAppearance</key>\n\t<false/>\n\t<key>CFBundleLocalizations</key>\n\t<array>\n\t\t<string>ar</string>\n\t\t<string>en</string>\n\t\t<string>es</string>\n\t\t<string>fa</string>\n\t\t<string>fr</string>\n\t\t<string>id</string>\n\t\t<string>pt-BR</string>\n\t\t<string>ru</string>\n\t\t<string>tr</string>\n\t\t<string>zh-CN</string>\n\t\t<string>zh-TW</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner/PrivacyInfo.xcprivacy",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>NSPrivacyAccessedAPITypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>C617.1</string>\n\t\t\t</array>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategoryDiskSpace</string>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>E174.1</string>\n\t\t\t</array>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategorySystemBootTime</string>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>35F9.1</string>\n\t\t\t</array>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategoryUserDefaults</string>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>1C8F.1</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner/Runner-Bridging-Header.h",
    "content": "#import \"GeneratedPluginRegistrant.h\"\n"
  },
  {
    "path": "ios/Runner/Runner.entitlements",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>aps-environment</key>\n\t<string>development</string>\n\t<key>com.apple.developer.networking.networkextension</key>\n\t<array>\n\t\t<string>app-proxy-provider</string>\n\t\t<string>dns-proxy</string>\n\t\t<string>packet-tunnel-provider</string>\n\t</array>\n\t<key>com.apple.developer.networking.vpn.api</key>\n\t<array>\n\t\t<string>allow-vpn</string>\n\t</array>\n\t<key>com.apple.security.app-sandbox</key>\n\t<true/>\n\t<key>com.apple.security.application-groups</key>\n\t<array>\n\t\t<string>group.$(BASE_BUNDLE_IDENTIFIER)</string>\n\t</array>\n\t<key>com.apple.security.network.client</key>\n\t<true/>\n\t<key>com.apple.security.network.server</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner/VPN/Helpers/Stored.swift",
    "content": "//\n//  Stored.swift\n//  Runner\n//\n//  Created by GFWFighter on 10/24/23.\n//\n\nimport Foundation\nimport Combine\n\nenum StoredLocation {\n    case standard\n    \n    func data(for key: String) -> Data? {\n        switch self {\n        case .standard:\n            return UserDefaults.standard.data(forKey: key)\n        }\n    }\n    \n    func set(_ value: Data, for key: String) {\n        switch self {\n        case .standard:\n            UserDefaults.standard.set(value, forKey: key)\n        }\n    }\n}\n\n\n@propertyWrapper\nstruct Stored<Value: Codable> {\n    let location: StoredLocation\n    let key: String\n    var wrappedValue: Value {\n        willSet {  // Before modifying wrappedValue\n            publisher.subject.send(newValue)\n            guard let value = try? JSONEncoder().encode(newValue) else {\n                return\n            }\n            location.set(value, for: key)\n        }\n    }\n\n    var projectedValue: Publisher {\n        publisher\n    }\n    private var publisher: Publisher\n    struct Publisher: Combine.Publisher {\n        typealias Output = Value\n        typealias Failure = Never\n        var subject: CurrentValueSubject<Value, Never> // PassthroughSubject will lack the call of initial assignment\n        func receive<S>(subscriber: S) where S: Subscriber, Self.Failure == S.Failure, Self.Output == S.Input {\n            subject.subscribe(subscriber)\n        }\n        init(_ output: Output) {\n            subject = .init(output)\n        }\n    }\n    init(wrappedValue: Value, key: String, in location: StoredLocation = .standard) {\n        self.location = location\n        self.key = key\n        var value = wrappedValue\n        if let data = location.data(for: key) {\n            do {\n                value = try JSONDecoder().decode(Value.self, from: data)\n            } catch {}\n        }\n        self.wrappedValue = value\n        publisher = Publisher(value)\n    }\n    static subscript<OuterSelf: ObservableObject>(\n        _enclosingInstance observed: OuterSelf,\n        wrapped wrappedKeyPath: ReferenceWritableKeyPath<OuterSelf, Value>,\n        storage storageKeyPath: ReferenceWritableKeyPath<OuterSelf, Self>\n    ) -> Value {\n        get {\n            observed[keyPath: storageKeyPath].wrappedValue\n        }\n        set {\n            if let subject = observed.objectWillChange as? ObservableObjectPublisher {\n                subject.send() // Before modifying wrappedValue\n                observed[keyPath: storageKeyPath].wrappedValue = newValue\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Runner/VPN/VPNConfig.swift",
    "content": "//\n//  VPNConfig.swift\n//  Runner\n//\n//  Created by GFWFighter on 10/24/23.\n//\n\nimport Foundation\nimport Combine\n\nclass VPNConfig: ObservableObject {\n    static let shared = VPNConfig()\n    \n    @Stored(key: \"VPN.ActiveConfigPath\")\n    var activeConfigPath: String = \"\"\n    \n    @Stored(key: \"VPN.ActiveProfileName\")\n    var activeProfileName: String = \"\"\n    \n    @Stored(key: \"VPN.GrpcServiceModePort\")\n    var grpcServiceModePort: Int = 0\n    \n    @Stored(key: \"VPN.workingDir\")\n    var workingDir: String = \"\"\n    \n    @Stored(key: \"VPN.tempDir\")\n    var tempDir: String = \"\"\n    \n    @Stored(key: \"VPN.baseDir\")\n    var baseDir: String = \"\"\n    \n//    @Stored(key: \"VPN.grpcFlutterPublicKey\")\n//    var grpcFlutterPublicKey: String = \"\"\n    \n    \n    @Stored(key: \"VPN.ConfigOptions\")\n    var configOptions: String = \"\"\n    \n    @Stored(key: \"VPN.DisableMemoryLimit\")\n    var disableMemoryLimit: Bool = false\n}\n"
  },
  {
    "path": "ios/Runner/VPN/VPNManager.swift",
    "content": "//\n//  VPNManager.swift\n//  Runner\n//\n//  Created by GFWFighter on 7/25/1402 AP.\n//\n\nimport Foundation\nimport Combine\nimport NetworkExtension\n\nenum VPNManagerAlertType: String {\n    case RequestVPNPermission\n    case RequestNotificationPermission\n    case EmptyConfiguration\n    case StartCommandServer\n    case CreateService\n    case StartService\n}\n\nstruct VPNManagerAlert {\n    let alert: VPNManagerAlertType?\n    let message: String?\n}\n\nclass VPNManager: ObservableObject {\n    private var cancelBag: Set<AnyCancellable> = []\n    \n    private var observer: NSObjectProtocol?\n    private var manager = NEVPNManager.shared()\n    private var loaded: Bool = false\n    private var timer: Timer?\n            \n    static let shared: VPNManager = VPNManager()\n        \n    @Published private(set) var state: NEVPNStatus = .invalid\n    @Published private(set) var alert: VPNManagerAlert = .init(alert: nil, message: nil)\n    \n    @Published private(set) var upload: Int64 = 0\n    @Published private(set) var download: Int64 = 0\n    @Published private(set) var elapsedTime: TimeInterval = 0\n    \n    private var _connectTime: Date?\n    private var connectTime: Date? {\n        set {\n            UserDefaults(suiteName: FilePath.groupName)?.set(newValue?.timeIntervalSince1970, forKey: \"SingBoxConnectTime\")\n            _connectTime = newValue\n        }\n        get {\n            if let _connectTime {\n                return _connectTime\n            }\n            guard let interval = UserDefaults(suiteName: FilePath.groupName)?.value(forKey: \"SingBoxConnectTime\") as? TimeInterval else {\n                return nil\n            }\n            return Date(timeIntervalSince1970: interval)\n        }\n    }\n    private var readingWS: Bool = false\n    \n    @Published var isConnectedToAnyVPN: Bool = false\n    \n    init() {\n        observer = NotificationCenter.default.addObserver(forName: .NEVPNStatusDidChange, object: nil, queue: nil) { [weak self] notification in\n            guard let connection = notification.object as? NEVPNConnection else { return }\n            self?.state = connection.status\n        }\n        \n        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in\n            guard let self else { return }\n            updateStats()\n            elapsedTime = -1 * (connectTime?.timeIntervalSinceNow ?? 0)\n        }\n    }\n                \n    deinit {\n        if let observer {\n            NotificationCenter.default.removeObserver(observer)\n        }\n        timer?.invalidate()\n    }\n    \n    func setup() async throws {\n        // guard !loaded else { return }\n        loaded = true\n        do {\n            try await loadVPNPreference()\n        } catch {\n            print(error.localizedDescription)\n        }\n    }\n    \n    private func loadVPNPreference() async throws {\n        do {\n            let managers = try await NETunnelProviderManager.loadAllFromPreferences()\n            if let manager = managers.first {\n                self.manager = manager\n                return\n            }\n            let newManager = NETunnelProviderManager()\n            let `protocol` = NETunnelProviderProtocol()\n            `protocol`.providerBundleIdentifier = Bundle.main.baseBundleIdentifier + \".HiddifyPacketTunnel\"\n            `protocol`.serverAddress = \"localhost\"\n            newManager.protocolConfiguration = `protocol`\n            newManager.localizedDescription = \"Hiddify\"\n            try await newManager.saveToPreferences()\n            try await newManager.loadFromPreferences()\n            self.manager = newManager\n        } catch {\n            print(error.localizedDescription)\t\n        }\n    }\n    \n    private func enableVPNManager() async throws {\n        manager.isEnabled = true\n        let rule = NEOnDemandRuleConnect()\n        rule.interfaceTypeMatch = .any\n        rule.probeURL = URL(string: \"http://captive.apple.com\")\n        manager.onDemandRules = [rule]\n        manager.isOnDemandEnabled = true\n        \n        do {\n            try await manager.saveToPreferences()\n            try await manager.loadFromPreferences()\n        } catch {\n            print(error.localizedDescription)\n        }\n    }\n    \n    @MainActor private func set(upload: Int64, download: Int64) {\n        self.upload = upload\n        self.download = download\n    }\n    \n    var isAnyVPNConnected: Bool {\n        guard let cfDict = CFNetworkCopySystemProxySettings() else { return false }\n        let nsDict = cfDict.takeRetainedValue() as NSDictionary\n        guard let keys = nsDict[\"__SCOPED__\"] as? NSDictionary else {\n            return false\n        }\n        for key: String in keys.allKeys as! [String] {\n            if key == \"tap\" || key == \"tun\" || key == \"ppp\" || key == \"ipsec\" || key == \"ipsec0\" {\n                return true\n            } else if key.starts(with: \"utun\") {\n                return true\n            }\n        }\n        return false\n    }\n    \n    func reset() {\n        loaded = false\n        if state != .disconnected && state != .invalid {\n            disconnect()\n        }\n        $state.filter { $0 == .disconnected || $0 == .invalid }.first().sink { [weak self] _ in\n            Task { [weak self] () in\n                self?.manager = .shared()\n                do {\n                    let managers = try await NETunnelProviderManager.loadAllFromPreferences()\n                    for manager in managers ?? [] {\n                        try await manager.removeFromPreferences()\n                    }\n                    try await self?.loadVPNPreference()\n                } catch {\n                    print(error.localizedDescription)\n                }\n            }\n        }.store(in: &cancelBag)\n        \n    }\n    \n    \n    private func updateStats() {\n        let isAnyVPNConnected = self.isAnyVPNConnected\n        if isConnectedToAnyVPN != isAnyVPNConnected {\n            isConnectedToAnyVPN = isAnyVPNConnected\n        }\n        guard state == .connected else { return }\n        guard let connection = manager.connection as? NETunnelProviderSession else { return }\n        do {\n            try connection.sendProviderMessage(\"stats\".data(using: .utf8)!) { [weak self] response in\n                guard\n                    let response,\n                    let response = String(data: response, encoding: .utf8)\n                else { return }\n                let responseComponents = response.components(separatedBy: \",\")\n                guard\n                    responseComponents.count == 2,\n                    let upload = Int64(responseComponents[0]),\n                    let download = Int64(responseComponents[1])\n                else { return }\n                Task { [upload, download, weak self] () in\n                    await self?.set(upload: upload, download: download)\n                }\n            }\n        } catch {\n            print(error.localizedDescription)\n        }\n    }\n    \n    func connect(with config: String, grpcServiceModePort:Int, disableMemoryLimit: Bool = false) async throws {\n        \n        await set(upload: 0, download: 0)\n//        guard state == .disconnected else { return }\n        do {\n            try await enableVPNManager()\n            try manager.connection.startVPNTunnel(options: [\n                \"Config\": config as NSString,\n                \"GrpcServiceModePort\":NSNumber(value: grpcServiceModePort),\n                \"DisableMemoryLimit\": (disableMemoryLimit ? \"YES\" : \"NO\") as NSString,\n            ])\n            \n        } catch {\n            print(error.localizedDescription)\n        }\n        connectTime = .now\n    }\n    \n    func disconnect() {\n        if manager.isOnDemandEnabled {\n            manager.isOnDemandEnabled = false\n            manager.onDemandRules = []\n            \n            manager.saveToPreferences { error in\n                if let error = error {\n                    print(\"save error:\", error)\n                    return\n                }\n            }\n        }\n\n//        guard state == .connected else { return }\n        manager.connection.stopVPNTunnel()\n    }\n}\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 54;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t032158B82ADDF8BF008D943B /* VPNManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032158B72ADDF8BF008D943B /* VPNManager.swift */; };\n\t\t032158BA2ADDFCC9008D943B /* TrafficReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032158B92ADDFCC9008D943B /* TrafficReader.swift */; };\n\t\t032158BC2ADDFD09008D943B /* SingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032158BB2ADDFD09008D943B /* SingBox.swift */; };\n\t\t03B516672AE6B93A00EA47E2 /* MethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B516662AE6B93A00EA47E2 /* MethodHandler.swift */; };\n\t\t03B516692AE7306B00EA47E2 /* StatusEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B516682AE7306B00EA47E2 /* StatusEventHandler.swift */; };\n\t\t03B5166B2AE7315E00EA47E2 /* AlertsEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B5166A2AE7315E00EA47E2 /* AlertsEventHandler.swift */; };\n\t\t03B5166D2AE7325500EA47E2 /* LogsEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B5166C2AE7325500EA47E2 /* LogsEventHandler.swift */; };\n\t\t03B516712AE74CCD00EA47E2 /* VPNConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B516702AE74CCD00EA47E2 /* VPNConfig.swift */; };\n\t\t03B516742AE74D2200EA47E2 /* Stored.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B516732AE74D2200EA47E2 /* Stored.swift */; };\n\t\t03B516762AE762F700EA47E2 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B516752AE762F700EA47E2 /* Logger.swift */; };\n\t\t03B516772AE7634400EA47E2 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B516752AE762F700EA47E2 /* Logger.swift */; };\n\t\t03B5167B2AE79DB400EA47E2 /* FileMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B5167A2AE79DB400EA47E2 /* FileMethodHandler.swift */; };\n\t\t03B5167D2AE7AC6200EA47E2 /* GroupsEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B5167C2AE7AC6200EA47E2 /* GroupsEventHandler.swift */; };\n\t\t03E392BB2ADDA00F000ADF15 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E392BA2ADDA00F000ADF15 /* PacketTunnelProvider.swift */; };\n\t\t03E392CC2ADDE078000ADF15 /* ExtensionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E392CB2ADDE078000ADF15 /* ExtensionProvider.swift */; };\n\t\t03E392CF2ADDEFC8000ADF15 /* FilePath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E392CE2ADDEFC8000ADF15 /* FilePath.swift */; };\n\t\t03E392D02ADDF1BD000ADF15 /* FilePath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E392CE2ADDEFC8000ADF15 /* FilePath.swift */; };\n\t\t03E392D22ADDF1F4000ADF15 /* ExtensionPlatformInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E392D12ADDF1F4000ADF15 /* ExtensionPlatformInterface.swift */; };\n\t\t03E392D42ADDF262000ADF15 /* Extension+RunBlocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E392D32ADDF262000ADF15 /* Extension+RunBlocking.swift */; };\n\t\t0736958B2B3AC96D007249BE /* Bundle+Properties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0736958A2B3AC96D007249BE /* Bundle+Properties.swift */; };\n\t\t0736958D2B3B79E0007249BE /* StatsEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0736958C2B3B79E0007249BE /* StatsEventHandler.swift */; };\n\t\t0736958F2B3B8048007249BE /* PlatformMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0736958E2B3B8047007249BE /* PlatformMethodHandler.swift */; };\n\t\t075637BA2B01583F005AFB8E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60F1D4AAC33ACF5C8307310D /* Pods_Runner.framework */; };\n\t\t1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };\n\t\t331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };\n\t\t3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };\n\t\t41E9FF922D1C0CC3003780C1 /* HiddifyPacketTunnel.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 03E392B62ADDA00E000ADF15 /* HiddifyPacketTunnel.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };\n\t\t41E9FF962D1C82BA003780C1 /* HiddifyCore.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 413270682C8A9BA2003A1E9B /* HiddifyCore.xcframework */; };\n\t\t59E8864FB99B37076B22F32B /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30560DB3EFDF5E86AAD00AB8 /* Pods_RunnerTests.framework */; };\n\t\t68885DD72B4EF33400D214BA /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E392B72ADDA00E000ADF15 /* NetworkExtension.framework */; };\n\t\t74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };\n\t\t97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };\n\t\t97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };\n\t\t97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };\n\t\tD703EE932B764EA3001D88B3 /* CommandClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = D703EE922B764EA3001D88B3 /* CommandClient.swift */; };\n\t\tD703EE962B765176001D88B3 /* ActiveGroupsEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D703EE952B765176001D88B3 /* ActiveGroupsEventHandler.swift */; };\n\t\tD7CC50862B768C50006BC140 /* Outbound.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7CC50852B768C50006BC140 /* Outbound.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t03E392BE2ADDA00F000ADF15 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 97C146E61CF9000F007C117D /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 03E392B52ADDA00E000ADF15;\n\t\t\tremoteInfo = HiddifyPacketTunnel;\n\t\t};\n\t\t331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 97C146E61CF9000F007C117D /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 97C146ED1CF9000F007C117D;\n\t\t\tremoteInfo = Runner;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t03E392C12ADDA00F000ADF15 /* Embed Foundation Extensions */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 13;\n\t\t\tfiles = (\n\t\t\t\t41E9FF922D1C0CC3003780C1 /* HiddifyPacketTunnel.appex in Embed Foundation Extensions */,\n\t\t\t);\n\t\t\tname = \"Embed Foundation Extensions\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t032158B72ADDF8BF008D943B /* VPNManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNManager.swift; sourceTree = \"<group>\"; };\n\t\t032158B92ADDFCC9008D943B /* TrafficReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrafficReader.swift; sourceTree = \"<group>\"; };\n\t\t032158BB2ADDFD09008D943B /* SingBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingBox.swift; sourceTree = \"<group>\"; };\n\t\t0337C822BEDF7A95576475B3 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-RunnerTests.debug.xcconfig\"; path = \"Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t03B516662AE6B93A00EA47E2 /* MethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MethodHandler.swift; sourceTree = \"<group>\"; };\n\t\t03B516682AE7306B00EA47E2 /* StatusEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEventHandler.swift; sourceTree = \"<group>\"; };\n\t\t03B5166A2AE7315E00EA47E2 /* AlertsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertsEventHandler.swift; sourceTree = \"<group>\"; };\n\t\t03B5166C2AE7325500EA47E2 /* LogsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogsEventHandler.swift; sourceTree = \"<group>\"; };\n\t\t03B516702AE74CCD00EA47E2 /* VPNConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNConfig.swift; sourceTree = \"<group>\"; };\n\t\t03B516732AE74D2200EA47E2 /* Stored.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stored.swift; sourceTree = \"<group>\"; };\n\t\t03B516752AE762F700EA47E2 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = \"<group>\"; };\n\t\t03B5167A2AE79DB400EA47E2 /* FileMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMethodHandler.swift; sourceTree = \"<group>\"; };\n\t\t03B5167C2AE7AC6200EA47E2 /* GroupsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupsEventHandler.swift; sourceTree = \"<group>\"; };\n\t\t03E392B62ADDA00E000ADF15 /* HiddifyPacketTunnel.appex */ = {isa = PBXFileReference; explicitFileType = \"wrapper.app-extension\"; includeInIndex = 0; path = HiddifyPacketTunnel.appex; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t03E392B72ADDA00E000ADF15 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };\n\t\t03E392BA2ADDA00F000ADF15 /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = \"<group>\"; };\n\t\t03E392BC2ADDA00F000ADF15 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t03E392BD2ADDA00F000ADF15 /* HiddifyPacketTunnel.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = HiddifyPacketTunnel.entitlements; sourceTree = \"<group>\"; };\n\t\t03E392C62ADDA064000ADF15 /* Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = \"<group>\"; };\n\t\t03E392C72ADDA26A000ADF15 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = \"<group>\"; };\n\t\t03E392CB2ADDE078000ADF15 /* ExtensionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionProvider.swift; sourceTree = \"<group>\"; };\n\t\t03E392CE2ADDEFC8000ADF15 /* FilePath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePath.swift; sourceTree = \"<group>\"; };\n\t\t03E392D12ADDF1F4000ADF15 /* ExtensionPlatformInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionPlatformInterface.swift; sourceTree = \"<group>\"; };\n\t\t03E392D32ADDF262000ADF15 /* Extension+RunBlocking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"Extension+RunBlocking.swift\"; sourceTree = \"<group>\"; };\n\t\t040FA3EB0673B72D60CC7145 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-RunnerTests.profile.xcconfig\"; path = \"Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t0736954E2B1FEB3E007249BE /* mobile_scanner.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = mobile_scanner.xcframework; path = ../build/ios/framework/Release/mobile_scanner.xcframework; sourceTree = \"<group>\"; };\n\t\t0736958A2B3AC96D007249BE /* Bundle+Properties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"Bundle+Properties.swift\"; sourceTree = \"<group>\"; };\n\t\t0736958C2B3B79E0007249BE /* StatsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsEventHandler.swift; sourceTree = \"<group>\"; };\n\t\t0736958E2B3B8047007249BE /* PlatformMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformMethodHandler.swift; sourceTree = \"<group>\"; };\n\t\t07A63A832B1E728C00CAFA4D /* Release */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Release; path = ../build/ios/framework/release; sourceTree = \"<group>\"; };\n\t\t07A63A842B1E72AE00CAFA4D /* App.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = App.xcframework; path = ../build/ios/framework/release/App.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A872B1E72C800CAFA4D /* Flutter.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Flutter.xcframework; path = ../build/ios/framework/release/Flutter.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A8C2B1E72FA00CAFA4D /* GTMSessionFetcher.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GTMSessionFetcher.xcframework; path = ../build/ios/framework/release/GTMSessionFetcher.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A8D2B1E72FB00CAFA4D /* package_info_plus.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = package_info_plus.xcframework; path = ../build/ios/framework/release/package_info_plus.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A8E2B1E72FB00CAFA4D /* SentryPrivate.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = SentryPrivate.xcframework; path = ../build/ios/framework/release/SentryPrivate.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A8F2B1E72FB00CAFA4D /* share_plus.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = share_plus.xcframework; path = ../build/ios/framework/release/share_plus.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A902B1E72FB00CAFA4D /* url_launcher_ios.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = url_launcher_ios.xcframework; path = ../build/ios/framework/release/url_launcher_ios.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A912B1E72FB00CAFA4D /* mobile_scanner.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = mobile_scanner.xcframework; path = ../build/ios/framework/release/mobile_scanner.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A922B1E72FB00CAFA4D /* sqlite3_flutter_libs.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = sqlite3_flutter_libs.xcframework; path = ../build/ios/framework/release/sqlite3_flutter_libs.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A932B1E72FB00CAFA4D /* cupertino_http.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = cupertino_http.xcframework; path = ../build/ios/framework/release/cupertino_http.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A942B1E72FB00CAFA4D /* flutter_native_splash.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = flutter_native_splash.xcframework; path = ../build/ios/framework/release/flutter_native_splash.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A952B1E72FB00CAFA4D /* FBLPromises.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FBLPromises.xcframework; path = ../build/ios/framework/release/FBLPromises.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A962B1E72FB00CAFA4D /* GoogleUtilities.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GoogleUtilities.xcframework; path = ../build/ios/framework/release/GoogleUtilities.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A972B1E72FB00CAFA4D /* device_info_plus.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = device_info_plus.xcframework; path = ../build/ios/framework/release/device_info_plus.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A982B1E72FB00CAFA4D /* GoogleDataTransport.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GoogleDataTransport.xcframework; path = ../build/ios/framework/release/GoogleDataTransport.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A992B1E72FB00CAFA4D /* sentry_flutter.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = sentry_flutter.xcframework; path = ../build/ios/framework/release/sentry_flutter.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A9A2B1E72FB00CAFA4D /* protocol_handler.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = protocol_handler.xcframework; path = ../build/ios/framework/release/protocol_handler.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A9B2B1E72FC00CAFA4D /* sqlite3.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = sqlite3.xcframework; path = ../build/ios/framework/release/sqlite3.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A9C2B1E72FC00CAFA4D /* GoogleToolboxForMac.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GoogleToolboxForMac.xcframework; path = ../build/ios/framework/release/GoogleToolboxForMac.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A9D2B1E72FC00CAFA4D /* GoogleUtilitiesComponents.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GoogleUtilitiesComponents.xcframework; path = ../build/ios/framework/release/GoogleUtilitiesComponents.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A9E2B1E72FC00CAFA4D /* nanopb.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = nanopb.xcframework; path = ../build/ios/framework/release/nanopb.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63A9F2B1E72FC00CAFA4D /* path_provider_foundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = path_provider_foundation.xcframework; path = ../build/ios/framework/release/path_provider_foundation.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63AA02B1E72FC00CAFA4D /* shared_preferences_foundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = shared_preferences_foundation.xcframework; path = ../build/ios/framework/release/shared_preferences_foundation.xcframework; sourceTree = \"<group>\"; };\n\t\t07A63AA12B1E72FC00CAFA4D /* Sentry.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Sentry.xcframework; path = ../build/ios/framework/release/Sentry.xcframework; sourceTree = \"<group>\"; };\n\t\t1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = \"<group>\"; };\n\t\t1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = \"<group>\"; };\n\t\t30560DB3EFDF5E86AAD00AB8 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = \"<group>\"; };\n\t\t331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = \"<group>\"; };\n\t\t413270682C8A9BA2003A1E9B /* HiddifyCore.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = HiddifyCore.xcframework; path = Frameworks/HiddifyCore.xcframework; sourceTree = \"<group>\"; };\n\t\t574F12C7748958784380337F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner.debug.xcconfig\"; path = \"Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t60F1D4AAC33ACF5C8307310D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t6836D3FA2B57FDFF00A79D75 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = \"<group>\"; };\n\t\t68DCEB762BD7D7590081FF65 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = \"<group>\"; };\n\t\t68DCEB772BD7DA3F0081FF65 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = \"<group>\"; };\n\t\t74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"Runner-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\t74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = \"<group>\"; };\n\t\t7CA62594950187FCFE36B54C /* Pods-Runner-HiddifyPacketTunnel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner-HiddifyPacketTunnel.debug.xcconfig\"; path = \"Target Support Files/Pods-Runner-HiddifyPacketTunnel/Pods-Runner-HiddifyPacketTunnel.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t808A94F72872B54716770416 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-RunnerTests.release.xcconfig\"; path = \"Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t90E93DE403BDFA627F3AA51E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner.release.xcconfig\"; path = \"Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = \"<group>\"; };\n\t\t9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = \"<group>\"; };\n\t\t97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t9AC67B4DCF829F5B6F63AA7D /* Pods-Runner-HiddifyPacketTunnel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner-HiddifyPacketTunnel.release.xcconfig\"; path = \"Target Support Files/Pods-Runner-HiddifyPacketTunnel/Pods-Runner-HiddifyPacketTunnel.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tC20A211B58CE31B2738D133C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner.profile.xcconfig\"; path = \"Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tD703EE922B764EA3001D88B3 /* CommandClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandClient.swift; sourceTree = \"<group>\"; };\n\t\tD703EE952B765176001D88B3 /* ActiveGroupsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveGroupsEventHandler.swift; sourceTree = \"<group>\"; };\n\t\tD7CC50852B768C50006BC140 /* Outbound.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Outbound.swift; sourceTree = \"<group>\"; };\n\t\tF3FFE1D9C2D5629FACC123EE /* Pods-Runner-HiddifyPacketTunnel.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner-HiddifyPacketTunnel.profile.xcconfig\"; path = \"Target Support Files/Pods-Runner-HiddifyPacketTunnel/Pods-Runner-HiddifyPacketTunnel.profile.xcconfig\"; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t03E392B32ADDA00E000ADF15 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t41E9FF962D1C82BA003780C1 /* HiddifyCore.xcframework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t531FE8242BCD501C24C8E9FA /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t59E8864FB99B37076B22F32B /* Pods_RunnerTests.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t97C146EB1CF9000F007C117D /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t075637BA2B01583F005AFB8E /* Pods_Runner.framework in Frameworks */,\n\t\t\t\t68885DD72B4EF33400D214BA /* NetworkExtension.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t032158B62ADDF8AF008D943B /* VPN */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03B516722AE74D1700EA47E2 /* Helpers */,\n\t\t\t\t032158B72ADDF8BF008D943B /* VPNManager.swift */,\n\t\t\t\t03B516702AE74CCD00EA47E2 /* VPNConfig.swift */,\n\t\t\t);\n\t\t\tpath = VPN;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03B5166E2AE7325D00EA47E2 /* Handlers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03B516662AE6B93A00EA47E2 /* MethodHandler.swift */,\n\t\t\t\t0736958E2B3B8047007249BE /* PlatformMethodHandler.swift */,\n\t\t\t\t03B516682AE7306B00EA47E2 /* StatusEventHandler.swift */,\n\t\t\t\t03B5167A2AE79DB400EA47E2 /* FileMethodHandler.swift */,\n\t\t\t\t03B5166A2AE7315E00EA47E2 /* AlertsEventHandler.swift */,\n\t\t\t\t03B5166C2AE7325500EA47E2 /* LogsEventHandler.swift */,\n\t\t\t\t03B5167C2AE7AC6200EA47E2 /* GroupsEventHandler.swift */,\n\t\t\t\t0736958C2B3B79E0007249BE /* StatsEventHandler.swift */,\n\t\t\t\tD703EE952B765176001D88B3 /* ActiveGroupsEventHandler.swift */,\n\t\t\t);\n\t\t\tpath = Handlers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03B516722AE74D1700EA47E2 /* Helpers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03B516732AE74D2200EA47E2 /* Stored.swift */,\n\t\t\t);\n\t\t\tpath = Helpers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03E392B92ADDA00F000ADF15 /* HiddifyPacketTunnel */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03E392CA2ADDE063000ADF15 /* SingBox */,\n\t\t\t\t03E392BA2ADDA00F000ADF15 /* PacketTunnelProvider.swift */,\n\t\t\t\t032158B92ADDFCC9008D943B /* TrafficReader.swift */,\n\t\t\t\t03B516752AE762F700EA47E2 /* Logger.swift */,\n\t\t\t\t03E392BC2ADDA00F000ADF15 /* Info.plist */,\n\t\t\t\t03E392BD2ADDA00F000ADF15 /* HiddifyPacketTunnel.entitlements */,\n\t\t\t\t68DCEB762BD7D7590081FF65 /* PrivacyInfo.xcprivacy */,\n\t\t\t);\n\t\t\tpath = HiddifyPacketTunnel;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03E392CA2ADDE063000ADF15 /* SingBox */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03E392CB2ADDE078000ADF15 /* ExtensionProvider.swift */,\n\t\t\t\t03E392D12ADDF1F4000ADF15 /* ExtensionPlatformInterface.swift */,\n\t\t\t\t03E392D32ADDF262000ADF15 /* Extension+RunBlocking.swift */,\n\t\t\t\t032158BB2ADDFD09008D943B /* SingBox.swift */,\n\t\t\t);\n\t\t\tpath = SingBox;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03E392CD2ADDE103000ADF15 /* Shared */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03E392CE2ADDEFC8000ADF15 /* FilePath.swift */,\n\t\t\t\tD703EE922B764EA3001D88B3 /* CommandClient.swift */,\n\t\t\t\tD7CC50852B768C50006BC140 /* Outbound.swift */,\n\t\t\t);\n\t\t\tpath = Shared;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t073695892B3AC954007249BE /* Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0736958A2B3AC96D007249BE /* Bundle+Properties.swift */,\n\t\t\t);\n\t\t\tpath = Extensions;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t311A4F4314861E02331B8DAC /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t574F12C7748958784380337F /* Pods-Runner.debug.xcconfig */,\n\t\t\t\t90E93DE403BDFA627F3AA51E /* Pods-Runner.release.xcconfig */,\n\t\t\t\tC20A211B58CE31B2738D133C /* Pods-Runner.profile.xcconfig */,\n\t\t\t\t7CA62594950187FCFE36B54C /* Pods-Runner-HiddifyPacketTunnel.debug.xcconfig */,\n\t\t\t\t9AC67B4DCF829F5B6F63AA7D /* Pods-Runner-HiddifyPacketTunnel.release.xcconfig */,\n\t\t\t\tF3FFE1D9C2D5629FACC123EE /* Pods-Runner-HiddifyPacketTunnel.profile.xcconfig */,\n\t\t\t\t0337C822BEDF7A95576475B3 /* Pods-RunnerTests.debug.xcconfig */,\n\t\t\t\t808A94F72872B54716770416 /* Pods-RunnerTests.release.xcconfig */,\n\t\t\t\t040FA3EB0673B72D60CC7145 /* Pods-RunnerTests.profile.xcconfig */,\n\t\t\t);\n\t\t\tpath = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t331C8082294A63A400263BE5 /* RunnerTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t331C807B294A618700263BE5 /* RunnerTests.swift */,\n\t\t\t);\n\t\t\tpath = RunnerTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6836D3FF2B57FECF00A79D75 /* Local Packages */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6836D3FA2B57FDFF00A79D75 /* Package.swift */,\n\t\t\t);\n\t\t\tpath = \"Local Packages\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9740EEB11CF90186004384FC /* Flutter */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,\n\t\t\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */,\n\t\t\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */,\n\t\t\t\t9740EEB31CF90195004384FC /* Generated.xcconfig */,\n\t\t\t\t03E392C62ADDA064000ADF15 /* Base.xcconfig */,\n\t\t\t);\n\t\t\tname = Flutter;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146E51CF9000F007C117D = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6836D3FF2B57FECF00A79D75 /* Local Packages */,\n\t\t\t\t03E392CD2ADDE103000ADF15 /* Shared */,\n\t\t\t\t9740EEB11CF90186004384FC /* Flutter */,\n\t\t\t\t97C146F01CF9000F007C117D /* Runner */,\n\t\t\t\t03E392B92ADDA00F000ADF15 /* HiddifyPacketTunnel */,\n\t\t\t\t97C146EF1CF9000F007C117D /* Products */,\n\t\t\t\t331C8082294A63A400263BE5 /* RunnerTests */,\n\t\t\t\t311A4F4314861E02331B8DAC /* Pods */,\n\t\t\t\tB8133545EEE13EDD5549E6A3 /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146EF1CF9000F007C117D /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146EE1CF9000F007C117D /* Runner.app */,\n\t\t\t\t331C8081294A63A400263BE5 /* RunnerTests.xctest */,\n\t\t\t\t03E392B62ADDA00E000ADF15 /* HiddifyPacketTunnel.appex */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146F01CF9000F007C117D /* Runner */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t073695892B3AC954007249BE /* Extensions */,\n\t\t\t\t03B5166E2AE7325D00EA47E2 /* Handlers */,\n\t\t\t\t032158B62ADDF8AF008D943B /* VPN */,\n\t\t\t\t74858FAE1ED2DC5600515810 /* AppDelegate.swift */,\n\t\t\t\t03E392C72ADDA26A000ADF15 /* Runner.entitlements */,\n\t\t\t\t97C146FA1CF9000F007C117D /* Main.storyboard */,\n\t\t\t\t97C146FD1CF9000F007C117D /* Assets.xcassets */,\n\t\t\t\t97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,\n\t\t\t\t97C147021CF9000F007C117D /* Info.plist */,\n\t\t\t\t1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,\n\t\t\t\t1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,\n\t\t\t\t74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,\n\t\t\t\t68DCEB772BD7DA3F0081FF65 /* PrivacyInfo.xcprivacy */,\n\t\t\t);\n\t\t\tpath = Runner;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tB8133545EEE13EDD5549E6A3 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t413270682C8A9BA2003A1E9B /* HiddifyCore.xcframework */,\n\t\t\t\t0736954E2B1FEB3E007249BE /* mobile_scanner.xcframework */,\n\t\t\t\t07A63A932B1E72FB00CAFA4D /* cupertino_http.xcframework */,\n\t\t\t\t07A63A972B1E72FB00CAFA4D /* device_info_plus.xcframework */,\n\t\t\t\t07A63A952B1E72FB00CAFA4D /* FBLPromises.xcframework */,\n\t\t\t\t07A63A942B1E72FB00CAFA4D /* flutter_native_splash.xcframework */,\n\t\t\t\t07A63A982B1E72FB00CAFA4D /* GoogleDataTransport.xcframework */,\n\t\t\t\t07A63A9C2B1E72FC00CAFA4D /* GoogleToolboxForMac.xcframework */,\n\t\t\t\t07A63A962B1E72FB00CAFA4D /* GoogleUtilities.xcframework */,\n\t\t\t\t07A63A9D2B1E72FC00CAFA4D /* GoogleUtilitiesComponents.xcframework */,\n\t\t\t\t07A63A8C2B1E72FA00CAFA4D /* GTMSessionFetcher.xcframework */,\n\t\t\t\t07A63A912B1E72FB00CAFA4D /* mobile_scanner.xcframework */,\n\t\t\t\t07A63A9E2B1E72FC00CAFA4D /* nanopb.xcframework */,\n\t\t\t\t07A63A8D2B1E72FB00CAFA4D /* package_info_plus.xcframework */,\n\t\t\t\t07A63A9F2B1E72FC00CAFA4D /* path_provider_foundation.xcframework */,\n\t\t\t\t07A63A9A2B1E72FB00CAFA4D /* protocol_handler.xcframework */,\n\t\t\t\t07A63A992B1E72FB00CAFA4D /* sentry_flutter.xcframework */,\n\t\t\t\t07A63AA12B1E72FC00CAFA4D /* Sentry.xcframework */,\n\t\t\t\t07A63A8E2B1E72FB00CAFA4D /* SentryPrivate.xcframework */,\n\t\t\t\t07A63A8F2B1E72FB00CAFA4D /* share_plus.xcframework */,\n\t\t\t\t07A63AA02B1E72FC00CAFA4D /* shared_preferences_foundation.xcframework */,\n\t\t\t\t07A63A922B1E72FB00CAFA4D /* sqlite3_flutter_libs.xcframework */,\n\t\t\t\t07A63A9B2B1E72FC00CAFA4D /* sqlite3.xcframework */,\n\t\t\t\t07A63A902B1E72FB00CAFA4D /* url_launcher_ios.xcframework */,\n\t\t\t\t07A63A872B1E72C800CAFA4D /* Flutter.xcframework */,\n\t\t\t\t07A63A842B1E72AE00CAFA4D /* App.xcframework */,\n\t\t\t\t07A63A832B1E728C00CAFA4D /* Release */,\n\t\t\t\t60F1D4AAC33ACF5C8307310D /* Pods_Runner.framework */,\n\t\t\t\t03E392B72ADDA00E000ADF15 /* NetworkExtension.framework */,\n\t\t\t\t30560DB3EFDF5E86AAD00AB8 /* Pods_RunnerTests.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t03E392B52ADDA00E000ADF15 /* HiddifyPacketTunnel */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 03E392C52ADDA00F000ADF15 /* Build configuration list for PBXNativeTarget \"HiddifyPacketTunnel\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t03E392B22ADDA00E000ADF15 /* Sources */,\n\t\t\t\t03E392B32ADDA00E000ADF15 /* Frameworks */,\n\t\t\t\t03E392B42ADDA00E000ADF15 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = HiddifyPacketTunnel;\n\t\t\tproductName = HiddifyPacketTunnel;\n\t\t\tproductReference = 03E392B62ADDA00E000ADF15 /* HiddifyPacketTunnel.appex */;\n\t\t\tproductType = \"com.apple.product-type.app-extension\";\n\t\t};\n\t\t331C8080294A63A400263BE5 /* RunnerTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget \"RunnerTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t2058E420D1A8B6F0E5E03873 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t331C807D294A63A400263BE5 /* Sources */,\n\t\t\t\t331C807F294A63A400263BE5 /* Resources */,\n\t\t\t\t531FE8242BCD501C24C8E9FA /* Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t331C8086294A63A400263BE5 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = RunnerTests;\n\t\t\tproductName = RunnerTests;\n\t\t\tproductReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t97C146ED1CF9000F007C117D /* Runner */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget \"Runner\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tB971F0749B278D190A7A7315 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t03E392C12ADDA00F000ADF15 /* Embed Foundation Extensions */,\n\t\t\t\t9740EEB61CF901F6004384FC /* Run Script */,\n\t\t\t\t97C146EC1CF9000F007C117D /* Resources */,\n\t\t\t\t97C146EA1CF9000F007C117D /* Sources */,\n\t\t\t\tFBEFD3291AEA65EDE2F5AEF6 /* [CP] Embed Pods Frameworks */,\n\t\t\t\t97C146EB1CF9000F007C117D /* Frameworks */,\n\t\t\t\t3B06AD1E1E4923F5004D2608 /* Thin Binary */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t03E392BF2ADDA00F000ADF15 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = Runner;\n\t\t\tproductName = Runner;\n\t\t\tproductReference = 97C146EE1CF9000F007C117D /* Runner.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t97C146E61CF9000F007C117D /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tBuildIndependentTargetsInParallel = YES;\n\t\t\t\tLastSwiftUpdateCheck = 1500;\n\t\t\t\tLastUpgradeCheck = 1510;\n\t\t\t\tORGANIZATIONNAME = \"\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t03E392B52ADDA00E000ADF15 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 15.0;\n\t\t\t\t\t\tDevelopmentTeamName = \"Mark Pashmfouroush\";\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\t331C8080294A63A400263BE5 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 14.0;\n\t\t\t\t\t\tDevelopmentTeamName = \"Mark Pashmfouroush\";\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t\tTestTargetID = 97C146ED1CF9000F007C117D;\n\t\t\t\t\t};\n\t\t\t\t\t97C146ED1CF9000F007C117D = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3.1;\n\t\t\t\t\t\tDevelopmentTeamName = \"Mark Pashmfouroush\";\n\t\t\t\t\t\tLastSwiftMigration = 1100;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject \"Runner\" */;\n\t\t\tcompatibilityVersion = \"Xcode 13.0\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 97C146E51CF9000F007C117D;\n\t\t\tpackageReferences = (\n\t\t\t\t413270672C8A9B88003A1E9B /* XCLocalSwiftPackageReference \"Local Packages\" */,\n\t\t\t);\n\t\t\tproductRefGroup = 97C146EF1CF9000F007C117D /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t97C146ED1CF9000F007C117D /* Runner */,\n\t\t\t\t331C8080294A63A400263BE5 /* RunnerTests */,\n\t\t\t\t03E392B52ADDA00E000ADF15 /* HiddifyPacketTunnel */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t03E392B42ADDA00E000ADF15 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t331C807F294A63A400263BE5 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t97C146EC1CF9000F007C117D /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,\n\t\t\t\t97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,\n\t\t\t\t97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t2058E420D1A8B6F0E5E03873 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\talwaysOutOfDate = 1;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}\",\n\t\t\t);\n\t\t\tname = \"Thin Binary\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"/bin/sh \\\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\\\" embed_and_thin\\n\";\n\t\t};\n\t\t9740EEB61CF901F6004384FC /* Run Script */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\talwaysOutOfDate = 1;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Run Script\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"/bin/sh \\\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\\\" build\\n\";\n\t\t};\n\t\tB971F0749B278D190A7A7315 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tFBEFD3291AEA65EDE2F5AEF6 /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist\",\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t03E392B22ADDA00E000ADF15 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t032158BA2ADDFCC9008D943B /* TrafficReader.swift in Sources */,\n\t\t\t\t032158BC2ADDFD09008D943B /* SingBox.swift in Sources */,\n\t\t\t\t03E392D22ADDF1F4000ADF15 /* ExtensionPlatformInterface.swift in Sources */,\n\t\t\t\t03E392CC2ADDE078000ADF15 /* ExtensionProvider.swift in Sources */,\n\t\t\t\t03E392BB2ADDA00F000ADF15 /* PacketTunnelProvider.swift in Sources */,\n\t\t\t\t03E392CF2ADDEFC8000ADF15 /* FilePath.swift in Sources */,\n\t\t\t\t03E392D42ADDF262000ADF15 /* Extension+RunBlocking.swift in Sources */,\n\t\t\t\t03B516762AE762F700EA47E2 /* Logger.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t331C807D294A63A400263BE5 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t97C146EA1CF9000F007C117D /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t03B516742AE74D2200EA47E2 /* Stored.swift in Sources */,\n\t\t\t\t03B5167B2AE79DB400EA47E2 /* FileMethodHandler.swift in Sources */,\n\t\t\t\t03B516772AE7634400EA47E2 /* Logger.swift in Sources */,\n\t\t\t\t74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,\n\t\t\t\tD703EE962B765176001D88B3 /* ActiveGroupsEventHandler.swift in Sources */,\n\t\t\t\t03B516712AE74CCD00EA47E2 /* VPNConfig.swift in Sources */,\n\t\t\t\t03B5166B2AE7315E00EA47E2 /* AlertsEventHandler.swift in Sources */,\n\t\t\t\t0736958B2B3AC96D007249BE /* Bundle+Properties.swift in Sources */,\n\t\t\t\t0736958D2B3B79E0007249BE /* StatsEventHandler.swift in Sources */,\n\t\t\t\t03B516692AE7306B00EA47E2 /* StatusEventHandler.swift in Sources */,\n\t\t\t\tD7CC50862B768C50006BC140 /* Outbound.swift in Sources */,\n\t\t\t\t032158B82ADDF8BF008D943B /* VPNManager.swift in Sources */,\n\t\t\t\t0736958F2B3B8048007249BE /* PlatformMethodHandler.swift in Sources */,\n\t\t\t\tD703EE932B764EA3001D88B3 /* CommandClient.swift in Sources */,\n\t\t\t\t03B516672AE6B93A00EA47E2 /* MethodHandler.swift in Sources */,\n\t\t\t\t03B5166D2AE7325500EA47E2 /* LogsEventHandler.swift in Sources */,\n\t\t\t\t03E392D02ADDF1BD000ADF15 /* FilePath.swift in Sources */,\n\t\t\t\t1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,\n\t\t\t\t03B5167D2AE7AC6200EA47E2 /* GroupsEventHandler.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t03E392BF2ADDA00F000ADF15 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 03E392B52ADDA00E000ADF15 /* HiddifyPacketTunnel */;\n\t\t\ttargetProxy = 03E392BE2ADDA00F000ADF15 /* PBXContainerItemProxy */;\n\t\t};\n\t\t331C8086294A63A400263BE5 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 97C146ED1CF9000F007C117D /* Runner */;\n\t\t\ttargetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t97C146FA1CF9000F007C117D /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146FB1CF9000F007C117D /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t97C147001CF9000F007C117D /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t03E392C22ADDA00F000ADF15 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 03E392C62ADDA064000ADF15 /* Base.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++20\";\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = HiddifyPacketTunnel/HiddifyPacketTunnel.entitlements;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 40102;\n\t\t\t\tDEVELOPMENT_TEAM = M7Q8ASP66Z;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tEXCLUDED_ARCHS = armv7;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_FILE = HiddifyPacketTunnel/Info.plist;\n\t\t\t\tINFOPLIST_KEY_CFBundleDisplayName = HiddifyPacketTunnel;\n\t\t\t\tINFOPLIST_KEY_NSHumanReadableCopyright = \"\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/usr/lib/swift\",\n\t\t\t\t\t\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t\t\"@executable_path/../hiddify-core/\",\n\t\t\t\t\t\"@executable_path/hiddify-core/\",\n\t\t\t\t);\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMARKETING_VERSION = 4.1.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tOTHER_LDFLAGS = \"-lresolv\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BASE_BUNDLE_IDENTIFIER).HiddifyPacketTunnel\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSUPPORTED_PLATFORMS = \"iphoneos iphonesimulator\";\n\t\t\t\tSUPPORTS_MACCATALYST = NO;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = \"DEBUG $(inherited)\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tTVOS_DEPLOYMENT_TARGET = 15.0;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t03E392C32ADDA00F000ADF15 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 03E392C62ADDA064000ADF15 /* Base.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++20\";\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = HiddifyPacketTunnel/HiddifyPacketTunnel.entitlements;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 40102;\n\t\t\t\tDEVELOPMENT_TEAM = M7Q8ASP66Z;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tEXCLUDED_ARCHS = armv7;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_FILE = HiddifyPacketTunnel/Info.plist;\n\t\t\t\tINFOPLIST_KEY_CFBundleDisplayName = HiddifyPacketTunnel;\n\t\t\t\tINFOPLIST_KEY_NSHumanReadableCopyright = \"\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/usr/lib/swift\",\n\t\t\t\t\t\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t\t\"@executable_path/../hiddify-core/\",\n\t\t\t\t\t\"@executable_path/hiddify-core/\",\n\t\t\t\t);\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMARKETING_VERSION = 4.1.2;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_LDFLAGS = \"-lresolv\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BASE_BUNDLE_IDENTIFIER).HiddifyPacketTunnel\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSUPPORTED_PLATFORMS = \"iphoneos iphonesimulator\";\n\t\t\t\tSUPPORTS_MACCATALYST = NO;\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tTVOS_DEPLOYMENT_TARGET = 15.0;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t03E392C42ADDA00F000ADF15 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 03E392C62ADDA064000ADF15 /* Base.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++20\";\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = HiddifyPacketTunnel/HiddifyPacketTunnel.entitlements;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 40102;\n\t\t\t\tDEVELOPMENT_TEAM = M7Q8ASP66Z;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tEXCLUDED_ARCHS = armv7;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_FILE = HiddifyPacketTunnel/Info.plist;\n\t\t\t\tINFOPLIST_KEY_CFBundleDisplayName = HiddifyPacketTunnel;\n\t\t\t\tINFOPLIST_KEY_NSHumanReadableCopyright = \"\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/usr/lib/swift\",\n\t\t\t\t\t\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t\t\"@executable_path/../hiddify-core/\",\n\t\t\t\t\t\"@executable_path/hiddify-core/\",\n\t\t\t\t);\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMARKETING_VERSION = 4.1.2;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_LDFLAGS = \"-lresolv\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BASE_BUNDLE_IDENTIFIER).HiddifyPacketTunnel\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSUPPORTED_PLATFORMS = \"iphoneos iphonesimulator\";\n\t\t\t\tSUPPORTS_MACCATALYST = NO;\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tTVOS_DEPLOYMENT_TARGET = 15.0;\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t249021D3217E4FDB00AE95B9 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = YES;\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"-fcxx-modules\",\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t);\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSUPPORTED_PLATFORMS = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t249021D4217E4FDB00AE95B9 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = \"$(inherited)\";\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tBUILD_LIBRARY_FOR_DISTRIBUTION = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEVELOPMENT_TEAM = M7Q8ASP66Z;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\t\"EXCLUDED_ARCHS[sdk=iphoneos*]\" = armv7;\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tINFOPLIST_KEY_LSApplicationCategoryType = \"public.app-category.utilities\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)\",\n\t\t\t\t\t\"$(SDKROOT)/usr/lib/swift\",\n\t\t\t\t\t\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t\t\"@executable_path/../hiddify-core/\",\n\t\t\t\t\t\"@executable_path/hiddify-core/\",\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"-fcxx-modules\",\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-ld_classic\",\n\t\t\t\t\t\"-lresolv\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BASE_BUNDLE_IDENTIFIER)\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSUPPORTED_PLATFORMS = \"iphoneos iphonesimulator\";\n\t\t\t\tSUPPORTS_MACCATALYST = NO;\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t331C8088294A63A400263BE5 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 0337C822BEDF7A95576475B3 /* Pods-RunnerTests.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 40102;\n\t\t\t\tDEVELOPMENT_TEAM = M7Q8ASP66Z;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tMARKETING_VERSION = 4.1.2;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.hiddify.ios.RunnerTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t331C8089294A63A400263BE5 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 808A94F72872B54716770416 /* Pods-RunnerTests.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 40102;\n\t\t\t\tDEVELOPMENT_TEAM = M7Q8ASP66Z;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tMARKETING_VERSION = 4.1.2;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.hiddify.ios.RunnerTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t331C808A294A63A400263BE5 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 040FA3EB0673B72D60CC7145 /* Pods-RunnerTests.profile.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 40102;\n\t\t\t\tDEVELOPMENT_TEAM = M7Q8ASP66Z;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tMARKETING_VERSION = 4.1.2;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.hiddify.ios.RunnerTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner\";\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t97C147031CF9000F007C117D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = YES;\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"-fcxx-modules\",\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t);\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t97C147041CF9000F007C117D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = YES;\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"-fcxx-modules\",\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t);\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSUPPORTED_PLATFORMS = iphoneos;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t97C147061CF9000F007C117D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = \"$(inherited)\";\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tBUILD_LIBRARY_FOR_DISTRIBUTION = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=macosx*]\" = \"Apple Development\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEVELOPMENT_TEAM = M7Q8ASP66Z;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\t\"EXCLUDED_ARCHS[sdk=iphoneos*]\" = armv7;\n\t\t\t\t\"EXCLUDED_ARCHS[sdk=iphonesimulator*]\" = \"i386 arm64\";\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tINFOPLIST_KEY_LSApplicationCategoryType = \"public.app-category.utilities\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)\",\n\t\t\t\t\t\"$(SDKROOT)/usr/lib/swift\",\n\t\t\t\t\t\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t\t\"@executable_path/../hiddify-core/\",\n\t\t\t\t\t\"@executable_path/hiddify-core/\",\n\t\t\t\t);\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"-fcxx-modules\",\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-ld_classic\",\n\t\t\t\t\t\"-lresolv\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BASE_BUNDLE_IDENTIFIER)\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSUPPORTED_PLATFORMS = \"iphoneos iphonesimulator\";\n\t\t\t\tSUPPORTS_MACCATALYST = NO;\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t97C147071CF9000F007C117D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = \"$(inherited)\";\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tBUILD_LIBRARY_FOR_DISTRIBUTION = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEVELOPMENT_TEAM = M7Q8ASP66Z;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\t\"EXCLUDED_ARCHS[sdk=iphoneos*]\" = armv7;\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tINFOPLIST_KEY_LSApplicationCategoryType = \"public.app-category.utilities\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)\",\n\t\t\t\t\t\"$(SDKROOT)/usr/lib/swift\",\n\t\t\t\t\t\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t\t\"@executable_path/../hiddify-core/\",\n\t\t\t\t\t\"@executable_path/hiddify-core/\",\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"-fcxx-modules\",\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-ld_classic\",\n\t\t\t\t\t\"-lresolv\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BASE_BUNDLE_IDENTIFIER)\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSUPPORTED_PLATFORMS = \"iphoneos iphonesimulator\";\n\t\t\t\tSUPPORTS_MACCATALYST = NO;\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t03E392C52ADDA00F000ADF15 /* Build configuration list for PBXNativeTarget \"HiddifyPacketTunnel\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t03E392C22ADDA00F000ADF15 /* Debug */,\n\t\t\t\t03E392C32ADDA00F000ADF15 /* Release */,\n\t\t\t\t03E392C42ADDA00F000ADF15 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget \"RunnerTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t331C8088294A63A400263BE5 /* Debug */,\n\t\t\t\t331C8089294A63A400263BE5 /* Release */,\n\t\t\t\t331C808A294A63A400263BE5 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t97C146E91CF9000F007C117D /* Build configuration list for PBXProject \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t97C147031CF9000F007C117D /* Debug */,\n\t\t\t\t97C147041CF9000F007C117D /* Release */,\n\t\t\t\t249021D3217E4FDB00AE95B9 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t97C147061CF9000F007C117D /* Debug */,\n\t\t\t\t97C147071CF9000F007C117D /* Release */,\n\t\t\t\t249021D4217E4FDB00AE95B9 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\n/* Begin XCLocalSwiftPackageReference section */\n\t\t413270672C8A9B88003A1E9B /* XCLocalSwiftPackageReference \"Local Packages\" */ = {\n\t\t\tisa = XCLocalSwiftPackageReference;\n\t\t\trelativePath = \"Local Packages\";\n\t\t};\n/* End XCLocalSwiftPackageReference section */\n\t};\n\trootObject = 97C146E61CF9000F007C117D /* Project object */;\n}\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>PreviewsEnabled</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner.xcodeproj/xcshareddata/xcschemes/HiddifyPacketTunnel.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1540\"\n   wasCreatedForAppExtension = \"YES\"\n   version = \"2.0\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"03E392B52ADDA00E000ADF15\"\n               BuildableName = \"HiddifyPacketTunnel.appex\"\n               BlueprintName = \"HiddifyPacketTunnel\"\n               ReferencedContainer = \"container:Runner.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n               BuildableName = \"Runner.app\"\n               BlueprintName = \"Runner\"\n               ReferencedContainer = \"container:Runner.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      shouldAutocreateTestPlan = \"YES\">\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Release\"\n      selectedDebuggerIdentifier = \"\"\n      selectedLauncherIdentifier = \"Xcode.IDEFoundation.Launcher.PosixSpawn\"\n      launchStyle = \"0\"\n      askForAppToLaunch = \"Yes\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\"\n      launchAutomaticallySubstyle = \"2\">\n      <RemoteRunnable\n         runnableDebuggingMode = \"0\"\n         BundleIdentifier = \"apple.hiddify.com\"\n         RemotePath = \"/var/containers/Bundle/Application/8EBA9FC7-47CA-4C36-B670-54E8EB45F196/Runner.app\">\n      </RemoteRunnable>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      askForAppToLaunch = \"Yes\"\n      launchAutomaticallySubstyle = \"2\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1510\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n               BuildableName = \"Runner.app\"\n               BlueprintName = \"Runner\"\n               ReferencedContainer = \"container:Runner.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      customLLDBInitFile = \"$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <Testables>\n         <TestableReference\n            skipped = \"NO\"\n            parallelizable = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"331C8080294A63A400263BE5\"\n               BuildableName = \"RunnerTests.xctest\"\n               BlueprintName = \"RunnerTests\"\n               ReferencedContainer = \"container:Runner.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      customLLDBInitFile = \"$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      enableGPUValidationMode = \"1\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n\n      <EnvironmentVariables>\n         <EnvironmentVariable\n            key = \"IDEPreferLogStreaming\"\n            value = \"YES\"\n            isEnabled = \"YES\">\n         </EnvironmentVariable>\n      </EnvironmentVariables>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Profile\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "ios/Runner.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodeproj\">\n   </FileRef>\n   <FileRef\n      location = \"group:Pods/Pods.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>PreviewsEnabled</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/RunnerTests/RunnerTests.swift",
    "content": "import Flutter\nimport UIKit\nimport XCTest\n\nclass RunnerTests: XCTestCase {\n\n  func testExample() {\n    // If you add code to the Runner application, consider adding tests here.\n    // See https://developer.apple.com/documentation/xctest for more information about using XCTest.\n  }\n\n}\n"
  },
  {
    "path": "ios/Shared/CommandClient.swift",
    "content": "import Foundation\nimport HiddifyCore\n\npublic class CommandClient: ObservableObject {\n    public enum ConnectionType {\n        case status\n        case groups\n        case log\n        case groupsInfoOnly\n    }\n    \n    private let connectionType: ConnectionType\n    private let logMaxLines: Int\n    private var commandClient: LibboxCommandClient?\n    private var connectTask: Task<Void, Error>?\n    \n    @Published private(set) var isConnected: Bool\n    @Published private(set) var status: LibboxStatusMessage?\n    @Published private(set) var groups: [SBGroup]?\n    @Published private(set) var logList: [String]\n    \n    public init(_ connectionType: ConnectionType, logMaxLines: Int = 300) {\n        self.connectionType = connectionType\n        self.logMaxLines = logMaxLines\n        logList = []\n        isConnected = false\n    }\n    \n    public func connect() {\n        if isConnected {\n            return\n        }\n        if let connectTask {\n            connectTask.cancel()\n        }\n        connectTask = Task {\n            await connect0()\n        }\n    }\n    \n    public func disconnect() {\n        if let connectTask {\n            connectTask.cancel()\n            self.connectTask = nil\n        }\n        if let commandClient {\n            try? commandClient.disconnect()\n            self.commandClient = nil\n        }\n    }\n    \n    private nonisolated func connect0() async {\n//        let clientOptions = LibboxCommandClientOptions()\n//        switch connectionType {\n//        case .status:\n//            clientOptions.command = LibboxCommandStatus\n//        case .groups:\n//            clientOptions.command = LibboxCommandGroup\n//        case .log:\n//            clientOptions.command = LibboxCommandLog\n//        case .groupsInfoOnly:\n//            clientOptions.command = LibboxCommandGroupInfoOnly\n//        }\n//        clientOptions.statusInterval = Int64(2 * NSEC_PER_SEC)\n//        let client = LibboxNewCommandClient(clientHandler(self), clientOptions)!\n//        do {\n//            for i in 0 ..< 10 {\n//                try await Task.sleep(nanoseconds: UInt64(Double(100 + (i * 50)) * Double(NSEC_PER_MSEC)))\n//                try Task.checkCancellation()\n//                do {\n//                    try client.connect()\n//                    await MainActor.run {\n//                        commandClient = client\n//                    }\n//                    return\n//                } catch {}\n//                try Task.checkCancellation()\n//            }\n//        } catch {\n//            try? client.disconnect()\n//        }\n    }\n    \n//    private class clientHandler: NSObject, LibboxCommandClientHandlerProtocol {\n//        \n//        \n//        private let commandClient: CommandClient\n//        \n//        init(_ commandClient: CommandClient) {\n//            self.commandClient = commandClient\n//        }\n//        \n//        func connected() {\n//            DispatchQueue.main.async { [self] in\n//                if commandClient.connectionType == .log {\n//                    commandClient.logList = []\n//                }\n//                commandClient.isConnected = true\n//            }\n//        }\n//        \n//        func disconnected(_: String?) {\n//            DispatchQueue.main.async { [self] in\n//                commandClient.isConnected = false\n//            }\n//        }\n//        \n//        func clearLogs() {\n//            DispatchQueue.main.async { [self] in\n//                commandClient.logList.removeAll()\n//            }\n//        }\n//        \n//        func writeLogs(_ messageList: (any LibboxStringIteratorProtocol)?) {\n////            guard let message else {\n////                return\n////            }\n////            DispatchQueue.main.async { [self] in\n////                if commandClient.logList.count > commandClient.logMaxLines {\n////                    commandClient.logList.removeFirst()\n////                }\n////                commandClient.logList.append(message)\n////            }\n//        }\n//        \n//        func writeStatus(_ message: LibboxStatusMessage?) {\n//            DispatchQueue.main.async { [self] in\n//                commandClient.status = message\n//            }\n//        }\n//        \n//        func writeGroups(_ groups: LibboxOutboundGroupIteratorProtocol?) {\n//            guard let groups else {\n//                return\n//            }\n//            var sbGroups = [SBGroup]()\n//            while groups.hasNext() {\n//                let group = groups.next()!\n//                var items = [SBItem]()\n//                let groupItems = group.getItems()\n//                while groupItems?.hasNext() ?? false {\n//                    let item = groupItems?.next()!\n//                    items.append(SBItem(tag: item!.tag,\n//                                        type: item!.type,\n//                                        urlTestDelay: Int(item!.urlTestDelay)\n//                                       )\n//                    )\n//                }\n//                \n//                sbGroups.append(.init(tag: group.tag,\n//                                      type: group.type,\n//                                      selected: group.selected,\n//                                      items: items)\n//                )\n//                \n//            }\n//            DispatchQueue.main.async { [self] in\n//                commandClient.groups = sbGroups\n//            }\n//        }\n//        \n//        func initializeClashMode(_ modeList: LibboxStringIteratorProtocol?, currentMode: String?) {\n//        }\n//        \n//        func updateClashMode(_ newMode: String?) {\n//        }\n//        func write(_ message: LibboxConnections?) {\n//        }\n//        \n//    }\n}\n"
  },
  {
    "path": "ios/Shared/FilePath.swift",
    "content": "//\n//  FilePath.swift\n//  SingBoxPacketTunnel\n//\n//  Created by GFWFighter on 7/25/1402 AP.\n//\n\nimport Foundation\n\npublic enum FilePath {\n    public static let packageName = {\n        Bundle.main.infoDictionary?[\"BASE_BUNDLE_IDENTIFIER\"] as? String ?? \"unknown\"\n    }()\n}\n\npublic extension FilePath {\n    static let groupName = \"group.\\(packageName)\"\n\n    private static let defaultSharedDirectory: URL! = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: FilePath.groupName)\n\n    static let sharedDirectory = defaultSharedDirectory!\n\n    static let cacheDirectory = sharedDirectory\n        .appendingPathComponent(\"Library\", isDirectory: true)\n        .appendingPathComponent(\"Caches\", isDirectory: true)\n\n    static let workingDirectory = cacheDirectory.appendingPathComponent(\"Working\", isDirectory: true)\n}\n\npublic extension URL {\n    var fileName: String {\n        var path = relativePath\n        if let index = path.lastIndex(of: \"/\") {\n            path = String(path[path.index(index, offsetBy: 1)...])\n        }\n        return path\n    }\n}\n"
  },
  {
    "path": "ios/Shared/Outbound.swift",
    "content": "public struct SBItem: Codable {\n    let tag: String\n    let type: String\n    let urlTestDelay: Int\n    \n    enum CodingKeys: String, CodingKey {\n        case tag\n        case type\n        case urlTestDelay = \"url-test-delay\"\n    }\n}\n\npublic struct SBGroup: Codable {\n    let tag: String\n    let type: String\n    let selected: String\n    let items: [SBItem]\n}\n"
  },
  {
    "path": "ios/exportOptions.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>destination</key>\n\t<string>export</string>\n\t<key>manageAppVersionAndBuildNumber</key>\n\t<true/>\n\t<key>method</key>\n\t<string>app-store</string>\n\t<key>provisioningProfiles</key>\n\t<dict>\n\t\t<key>apple.hiddify.com</key>\n\t\t<string>dist.apple.apple.hiddify.com</string>\n\t\t<key>apple.hiddify.com.SingBoxPacketTunnel</key>\n\t\t<string>dist.apple.apple.hiddify.com.singboxpackettunnel</string>\n\t</dict>\n\t<key>signingCertificate</key>\n\t<string>E2217AF6F3AD11BA09F9FD95E025D7E637F8B081</string>\n\t<key>signingStyle</key>\n\t<string>manual</string>\n\t<key>stripSwiftSymbols</key>\n\t<true/>\n\t<key>teamID</key>\n\t<string>3JFTY5BP58</string>\n\t<key>uploadSymbols</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/packaging/ios/make_config.yaml",
    "content": "display_name: Hiddify\n\nicon: ..\\..\\assets\\images\\windows.ico\n\nkeywords:\n  - Hiddify\n  - Proxy\n  - VPN\n  - V2ray\n  - Nekoray\n  - Xray\n  - Psiphon\n  - OpenVPN\n\ngeneric_name: Hiddify\n\nactions:\n  - name: Start\n    label: start\n    arguments:\n      - --start\n  - name: Stop\n    label: stop\n    arguments:\n      - --stop\n\ncategories:\n  - Internet\n\nstartup_notify: true\n\n# You can specify the shared libraries that you want to bundle with your app\n#\n# flutter_distributor automatically detects the shared libraries that your app\n# depends on, but you can also specify them manually here.\n# \n# The following example shows how to bundle the libcurl library with your app.\n#\n# include:\n#   - libcurl.so.4\ninclude: []\n\n"
  },
  {
    "path": "lib/bootstrap.dart",
    "content": "import 'dart:async';\nimport 'dart:io';\n\nimport 'package:flutter/foundation.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_displaymode/flutter_displaymode.dart';\nimport 'package:flutter_native_splash/flutter_native_splash.dart';\nimport 'package:hiddify/core/analytics/analytics_controller.dart';\nimport 'package:hiddify/core/app_info/app_info_provider.dart';\nimport 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/logger/logger.dart';\nimport 'package:hiddify/core/logger/logger_controller.dart';\nimport 'package:hiddify/core/model/environment.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/preferences/preferences_migration.dart';\nimport 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/features/app/widget/app.dart';\nimport 'package:hiddify/features/auto_start/notifier/auto_start_notifier.dart';\n\nimport 'package:hiddify/features/log/data/log_data_providers.dart';\nimport 'package:hiddify/features/profile/data/profile_data_providers.dart';\nimport 'package:hiddify/features/profile/notifier/active_profile_notifier.dart';\nimport 'package:hiddify/features/system_tray/notifier/system_tray_notifier.dart';\nimport 'package:hiddify/features/window/notifier/window_notifier.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service_provider.dart';\nimport 'package:hiddify/riverpod_observer.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:sentry_flutter/sentry_flutter.dart';\n\nFuture<void> lazyBootstrap(WidgetsBinding widgetsBinding, Environment env) async {\n  if (!kIsWeb) {\n    FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);\n  }\n  LoggerController.preInit();\n  FlutterError.onError = Logger.logFlutterError;\n  WidgetsBinding.instance.platformDispatcher.onError = Logger.logPlatformDispatcherError;\n\n  final stopWatch = Stopwatch()..start();\n\n  final container = ProviderContainer(overrides: [environmentProvider.overrideWithValue(env)]);\n\n  await _init(\"directories\", () => container.read(appDirectoriesProvider.future));\n  LoggerController.init(container.read(logPathResolverProvider).appFile().path);\n\n  final appInfo = await _init(\"app info\", () => container.read(appInfoProvider.future));\n  await _init(\"preferences\", () => container.read(sharedPreferencesProvider.future));\n\n  final enableAnalytics = await container.read(analyticsControllerProvider.future);\n  if (enableAnalytics) {\n    await _init(\"analytics\", () => container.read(analyticsControllerProvider.notifier).enableAnalytics());\n  }\n\n  await _init(\"preferences migration\", () async {\n    try {\n      await PreferencesMigration(sharedPreferences: container.read(sharedPreferencesProvider).requireValue).migrate();\n    } catch (e, stackTrace) {\n      Logger.bootstrap.error(\"preferences migration failed\", e, stackTrace);\n      if (env == Environment.dev) rethrow;\n      Logger.bootstrap.info(\"clearing preferences\");\n      await container.read(sharedPreferencesProvider).requireValue.clear();\n    }\n  });\n\n  final debug = container.read(debugModeNotifierProvider) || kDebugMode;\n\n  if (PlatformUtils.isDesktop) {\n    await _init(\"window controller\", () => container.read(windowNotifierProvider.future));\n\n    final silentStart = container.read(Preferences.silentStart);\n    Logger.bootstrap.debug(\"silent start [${silentStart ? \"Enabled\" : \"Disabled\"}]\");\n    if (!silentStart) {\n      await container.read(windowNotifierProvider.notifier).show(focus: false);\n    } else {\n      Logger.bootstrap.debug(\"silent start, remain hidden accessible via tray\");\n    }\n    await _init(\"auto start service\", () => container.read(autoStartNotifierProvider.future));\n  }\n  await _init(\"logs repository\", () => container.read(logRepositoryProvider.future));\n  await _init(\"logger controller\", () => LoggerController.postInit(debug));\n\n  Logger.bootstrap.info(appInfo.format());\n\n  await _init(\"profile repository\", () => container.read(profileRepositoryProvider.future));\n\n  await _init(\"translations\", () => container.read(translationsProvider.future));\n\n  await _safeInit(\"active profile\", () => container.read(activeProfileProvider.future), timeout: 1000);\n  await _init(\"hiddify-core\", () => container.read(hiddifyCoreServiceProvider).init());\n\n  if (!kIsWeb) {\n    // await _safeInit(\n    //   \"deep link service\",\n    //   () => container.read(deepLinkNotifierProvider.future),\n    //   timeout: 1000,\n    // );\n\n    if (PlatformUtils.isDesktop) {\n      await _safeInit(\"system tray\", () => container.read(systemTrayNotifierProvider.future), timeout: 1000);\n    }\n\n    if (PlatformUtils.isAndroid) {\n      await _safeInit(\"android display mode\", () async {\n        await FlutterDisplayMode.setHighRefreshRate();\n      });\n    }\n  }\n\n  Logger.bootstrap.info(\"bootstrap took [${stopWatch.elapsedMilliseconds}ms]\");\n  stopWatch.stop();\n\n  runApp(\n    ProviderScope(\n      parent: container,\n      observers: [RiverpodObserver()],\n      child: SentryUserInteractionWidget(child: const App()),\n    ),\n  );\n\n  if (!kIsWeb) {\n    FlutterNativeSplash.remove();\n  }\n  // SentryFlutter.s(DateTime.now().toUtc());\n}\n\nFuture<T> _init<T>(String name, Future<T> Function() initializer, {int? timeout}) async {\n  final stopWatch = Stopwatch()..start();\n  Logger.bootstrap.info(\"initializing [$name]\");\n  Future<T> func() => timeout != null ? initializer().timeout(Duration(milliseconds: timeout)) : initializer();\n  try {\n    final result = await func();\n    Logger.bootstrap.debug(\"[$name] initialized in ${stopWatch.elapsedMilliseconds}ms\");\n    return result;\n  } catch (e, stackTrace) {\n    Logger.bootstrap.error(\"[$name] error initializing\", e, stackTrace);\n    rethrow;\n  } finally {\n    stopWatch.stop();\n  }\n}\n\nFuture<T?> _safeInit<T>(String name, Future<T> Function() initializer, {int? timeout}) async {\n  try {\n    return await _init(name, initializer, timeout: timeout);\n  } catch (e) {\n    return null;\n  }\n}\n"
  },
  {
    "path": "lib/core/analytics/analytics_controller.dart",
    "content": "import 'package:flutter/foundation.dart';\nimport 'package:hiddify/core/analytics/analytics_filter.dart';\nimport 'package:hiddify/core/analytics/analytics_logger.dart';\n\nimport 'package:hiddify/core/logger/logger_controller.dart';\nimport 'package:hiddify/core/model/environment.dart';\nimport 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:sentry_flutter/sentry_flutter.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\npart 'analytics_controller.g.dart';\n\nconst String enableAnalyticsPrefKey = \"enable_analytics\";\n\nbool _testCrashReport = false;\n\n@Riverpod(keepAlive: true)\nclass AnalyticsController extends _$AnalyticsController with AppLogger {\n  @override\n  Future<bool> build() async {\n    return _preferences.getBool(enableAnalyticsPrefKey) ?? true;\n  }\n\n  SharedPreferences get _preferences => ref.read(sharedPreferencesProvider).requireValue;\n\n  Future<void> enableAnalytics() async {\n    if (state case AsyncData(value: final enabled)) {\n      loggy.debug(\"enabling analytics\");\n      state = const AsyncLoading();\n      if (!enabled) {\n        await _preferences.setBool(enableAnalyticsPrefKey, true);\n      }\n\n      // final env = ref.read(environmentProvider);\n      // final appInfo = await ref.read(appInfoProvider.future);\n      final dsn = !kDebugMode || _testCrashReport ? Environment.sentryDSN : \"\";\n      final sentryLogger = SentryLoggyIntegration();\n      LoggerController.instance.addPrinter(\"analytics\", sentryLogger);\n\n      await SentryFlutter.init((options) {\n        options.dsn = dsn;\n        // options.environment = env.name;\n        // options.dist = appInfo.release.name;\n        options.debug = kDebugMode;\n        options.enableNativeCrashHandling = true;\n        options.enableNdkScopeSync = true;\n        // options.autoAppStart = false;\n        // options.attachScreenshot = true;\n        options.serverName = \"\";\n        options.attachThreads = true;\n        options.tracesSampleRate = 0.20;\n        options.enableUserInteractionTracing = true;\n        options.addIntegration(sentryLogger);\n        options.beforeSend = sentryBeforeSend;\n      });\n\n      state = const AsyncData(true);\n    }\n  }\n\n  Future<void> disableAnalytics() async {\n    if (state case AsyncData()) {\n      loggy.debug(\"disabling analytics\");\n      state = const AsyncLoading();\n      await _preferences.setBool(enableAnalyticsPrefKey, false);\n      await Sentry.close();\n      LoggerController.instance.removePrinter(\"analytics\");\n      state = const AsyncData(false);\n    }\n  }\n}\n"
  },
  {
    "path": "lib/core/analytics/analytics_filter.dart",
    "content": "import 'dart:io';\n\nimport 'package:dio/dio.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:sentry_flutter/sentry_flutter.dart';\n\nFutureOr<SentryEvent?> sentryBeforeSend(SentryEvent event, Hint hint) async {\n  if (!canSendEvent(event.throwable)) return null;\n  return event.copyWith(\n    user: SentryUser(email: \"\", username: \"\", ipAddress: \"0.0.0.0\"),\n  );\n}\n\nbool canSendEvent(dynamic throwable) {\n  return switch (throwable) {\n    UnexpectedFailure(:final error) => canSendEvent(error),\n    DioException _ => false,\n    SocketException _ => false,\n    HttpException _ => false,\n    HandshakeException _ => false,\n    ExpectedFailure _ => false,\n    ExpectedMeasuredFailure _ => false,\n    _ => true,\n  };\n}\n\nbool canLogEvent(dynamic throwable) => switch (throwable) {\n  ExpectedMeasuredFailure _ => true,\n  _ => canSendEvent(throwable),\n};\n"
  },
  {
    "path": "lib/core/analytics/analytics_logger.dart",
    "content": "import 'package:hiddify/utils/sentry_utils.dart';\nimport 'package:loggy/loggy.dart';\nimport 'package:sentry_flutter/sentry_flutter.dart';\n\n// modified version of https://github.com/getsentry/sentry-dart/tree/main/logging\nclass SentryLoggyIntegration extends LoggyPrinter implements Integration<SentryOptions> {\n  SentryLoggyIntegration({LogLevel minBreadcrumbLevel = LogLevel.info, LogLevel minEventLevel = LogLevel.error})\n    : _minBreadcrumbLevel = minBreadcrumbLevel,\n      _minEventLevel = minEventLevel;\n\n  final LogLevel _minBreadcrumbLevel;\n  final LogLevel _minEventLevel;\n\n  late Hub _hub;\n\n  @override\n  void call(Hub hub, SentryOptions options) {\n    _hub = hub;\n    options.sdk.addIntegration('LoggyIntegration');\n  }\n\n  @override\n  Future<void> close() async {}\n\n  bool _shouldLog(LogLevel logLevel, LogLevel minLevel) {\n    if (logLevel == LogLevel.off) {\n      return false;\n    }\n    return logLevel.priority >= minLevel.priority;\n  }\n\n  @override\n  Future<void> onLog(LogRecord record) async {\n    if (!canLogEvent(record.error)) return;\n\n    if (_shouldLog(record.level, _minEventLevel)) {\n      await _hub.captureEvent(\n        record.toEvent(),\n        stackTrace: record.stackTrace,\n        hint: Hint.withMap({TypeCheckHint.record: record}),\n      );\n    }\n\n    if (_shouldLog(record.level, _minBreadcrumbLevel)) {\n      await _hub.addBreadcrumb(record.toBreadcrumb(), hint: Hint.withMap({TypeCheckHint.record: record}));\n    }\n  }\n}\n\nextension LogRecordX on LogRecord {\n  Breadcrumb toBreadcrumb() {\n    return Breadcrumb(\n      category: 'log',\n      type: 'debug',\n      timestamp: time.toUtc(),\n      level: level.toSentryLevel(),\n      message: message,\n      data: <String, Object>{\n        if (object != null) 'LogRecord.object': object!,\n        if (error != null) 'LogRecord.error': error!,\n        if (stackTrace != null) 'LogRecord.stackTrace': stackTrace!,\n        'LogRecord.loggerName': loggerName,\n        'LogRecord.sequenceNumber': sequenceNumber,\n      },\n    );\n  }\n\n  SentryEvent toEvent() {\n    return SentryEvent(\n      timestamp: time.toUtc(),\n      logger: loggerName,\n      level: level.toSentryLevel(),\n      message: SentryMessage(message),\n      throwable: error,\n      // ignore: deprecated_member_use\n      extra: <String, Object>{\n        if (object != null) 'LogRecord.object': object!,\n        'LogRecord.sequenceNumber': sequenceNumber,\n      },\n    );\n  }\n}\n\nextension LogLevelX on LogLevel {\n  SentryLevel? toSentryLevel() => switch (this) {\n    LogLevel.all || LogLevel.debug => SentryLevel.debug,\n    LogLevel.info => SentryLevel.info,\n    LogLevel.warning => SentryLevel.warning,\n    LogLevel.error => SentryLevel.error,\n    _ => null,\n  };\n}\n"
  },
  {
    "path": "lib/core/app_info/app_info_provider.dart",
    "content": "import 'dart:io';\n\nimport 'package:flutter/foundation.dart';\nimport 'package:hiddify/core/model/app_info_entity.dart';\nimport 'package:hiddify/core/model/environment.dart';\nimport 'package:package_info_plus/package_info_plus.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'app_info_provider.g.dart';\n\n@Riverpod(keepAlive: true)\nEnvironment environment(EnvironmentRef ref) => throw Exception(\"override environmentProvider\");\n\n@Riverpod(keepAlive: true)\nclass AppInfo extends _$AppInfo {\n  @override\n  Future<AppInfoEntity> build() async {\n    final packageInfo = await PackageInfo.fromPlatform();\n    final environment = ref.watch(environmentProvider);\n    return AppInfoEntity(\n      name: packageInfo.appName,\n      version: packageInfo.version,\n      buildNumber: packageInfo.buildNumber,\n      release: Release.read(),\n      operatingSystem: kIsWeb ? \"web\" : Platform.operatingSystem,\n      operatingSystemVersion: kIsWeb ? \"web\" : Platform.operatingSystemVersion,\n      environment: environment,\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/db/converters/duration_converter.dart",
    "content": "import 'package:drift/drift.dart';\n\nclass DurationTypeConverter extends TypeConverter<Duration, int> {\n  @override\n  Duration fromSql(int fromDb) {\n    return Duration(seconds: fromDb);\n  }\n\n  @override\n  int toSql(Duration value) {\n    return value.inSeconds;\n  }\n}\n"
  },
  {
    "path": "lib/core/db/db.dart",
    "content": "import 'package:drift/drift.dart';\nimport 'package:drift_flutter/drift_flutter.dart';\nimport 'package:hiddify/core/db/converters/duration_converter.dart';\nimport 'package:hiddify/core/db/db.steps.dart';\nimport 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_mode.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\n\npart 'db.g.dart';\n\n@DriftDatabase(tables: [ProfileEntries, AppProxyEntries])\nclass Db extends _$Db with InfraLogger {\n  Db([QueryExecutor? executor]) : super(executor ?? _openConnection());\n\n  @override\n  int get schemaVersion => 5;\n\n  static QueryExecutor _openConnection() {\n    return LazyDatabase(\n      () => driftDatabase(\n        name: \"db\",\n        native: const DriftNativeOptions(databaseDirectory: AppDirectories.getDatabaseDirectory),\n        web: DriftWebOptions(sqlite3Wasm: Uri.parse('sqlite3.wasm'), driftWorker: Uri.parse('drift_worker.js')),\n      ),\n    );\n  }\n\n  @override\n  MigrationStrategy get migration {\n    return MigrationStrategy(\n      onCreate: (Migrator m) async {\n        await m.createAll();\n      },\n      onUpgrade: stepByStep(\n        from1To2: (m, schema) async {\n          await m.alterTable(\n            TableMigration(\n              schema.profileEntries,\n              columnTransformer: {schema.profileEntries.type: const Constant<String>(\"remote\")},\n              newColumns: [schema.profileEntries.type],\n            ),\n          );\n        },\n        from2To3: (m, schema) async {\n          await m.createTable(schema.geoAssetEntries);\n        },\n        from3To4: (m, schema) async {\n          final testUrlExists = await _columnExists(\n            schema.profileEntries.actualTableName,\n            schema.profileEntries.testUrl.name,\n          );\n          if (!testUrlExists) {\n            await m.addColumn(schema.profileEntries, schema.profileEntries.testUrl);\n          }\n        },\n        from4To5: (m, schema) async {\n          await m.deleteTable('geo_asset_entries');\n          await m.renameColumn(schema.profileEntries, 'test_url', schema.profileEntries.profileOverride);\n\n          final userOverrideExists = await _columnExists(\n            schema.profileEntries.actualTableName,\n            schema.profileEntries.userOverride.name,\n          );\n          if (!userOverrideExists) {\n            await m.addColumn(schema.profileEntries, schema.profileEntries.userOverride);\n          }\n\n          final populatedHeadersExists = await _columnExists(\n            schema.profileEntries.actualTableName,\n            schema.profileEntries.populatedHeaders.name,\n          );\n          if (!populatedHeadersExists) {\n            await m.addColumn(schema.profileEntries, schema.profileEntries.populatedHeaders);\n          }\n\n          await m.createTable(schema.appProxyEntries);\n        },\n      ),\n    );\n  }\n\n  Future<bool> _columnExists(String table, String column) async {\n    final result = await customSelect('PRAGMA table_info($table);').get();\n    return result.any((row) => row.data['name'] == column);\n  }\n}\n\n@DataClassName('ProfileEntry')\nclass ProfileEntries extends Table {\n  TextColumn get id => text()();\n  TextColumn get type => textEnum<ProfileType>()();\n  BoolColumn get active => boolean()();\n  TextColumn get name => text().withLength(min: 1)();\n  TextColumn get url => text().nullable()();\n  DateTimeColumn get lastUpdate => dateTime()();\n  IntColumn get updateInterval => integer().nullable().map(DurationTypeConverter())();\n  IntColumn get upload => integer().nullable()();\n  IntColumn get download => integer().nullable()();\n  IntColumn get total => integer().nullable()();\n  DateTimeColumn get expire => dateTime().nullable()();\n  TextColumn get webPageUrl => text().nullable()();\n  TextColumn get supportUrl => text().nullable()();\n  TextColumn get populatedHeaders => text().nullable()();\n  TextColumn get profileOverride => text().nullable()();\n  TextColumn get userOverride => text().nullable()();\n\n  @override\n  Set<Column> get primaryKey => {id};\n}\n\n@DataClassName('AppProxyEntry')\nclass AppProxyEntries extends Table {\n  TextColumn get mode => textEnum<AppProxyMode>()();\n  TextColumn get pkgName => text()();\n  IntColumn get flags => integer().withDefault(const Constant(0))();\n\n  @override\n  Set<Column> get primaryKey => {mode, pkgName};\n}\n"
  },
  {
    "path": "lib/core/db/db.steps.dart",
    "content": "// dart format width=80\nimport 'package:drift/internal/versioned_schema.dart' as i0;\nimport 'package:drift/drift.dart' as i1;\nimport 'package:drift/drift.dart'; // ignore_for_file: type=lint,unused_import\n\n// GENERATED BY drift_dev, DO NOT MODIFY.\nfinal class Schema2 extends i0.VersionedSchema {\n  Schema2({required super.database}) : super(version: 2);\n  @override\n  late final List<i1.DatabaseSchemaEntity> entities = [profileEntries];\n  late final Shape0 profileEntries = Shape0(\n    source: i0.VersionedTable(\n      entityName: 'profile_entries',\n      withoutRowId: false,\n      isStrict: false,\n      tableConstraints: ['PRIMARY KEY(id)'],\n      columns: [\n        _column_0,\n        _column_1,\n        _column_2,\n        _column_3,\n        _column_4,\n        _column_5,\n        _column_6,\n        _column_7,\n        _column_8,\n        _column_9,\n        _column_10,\n        _column_11,\n        _column_12,\n      ],\n      attachedDatabase: database,\n    ),\n    alias: null,\n  );\n}\n\nclass Shape0 extends i0.VersionedTable {\n  Shape0({required super.source, required super.alias}) : super.aliased();\n  i1.GeneratedColumn<String> get id =>\n      columnsByName['id']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get type =>\n      columnsByName['type']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<bool> get active =>\n      columnsByName['active']! as i1.GeneratedColumn<bool>;\n  i1.GeneratedColumn<String> get name =>\n      columnsByName['name']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get url =>\n      columnsByName['url']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<DateTime> get lastUpdate =>\n      columnsByName['last_update']! as i1.GeneratedColumn<DateTime>;\n  i1.GeneratedColumn<int> get updateInterval =>\n      columnsByName['update_interval']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<int> get upload =>\n      columnsByName['upload']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<int> get download =>\n      columnsByName['download']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<int> get total =>\n      columnsByName['total']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<DateTime> get expire =>\n      columnsByName['expire']! as i1.GeneratedColumn<DateTime>;\n  i1.GeneratedColumn<String> get webPageUrl =>\n      columnsByName['web_page_url']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get supportUrl =>\n      columnsByName['support_url']! as i1.GeneratedColumn<String>;\n}\n\ni1.GeneratedColumn<String> _column_0(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'id',\n      aliasedName,\n      false,\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<String> _column_1(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'type',\n      aliasedName,\n      false,\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<bool> _column_2(String aliasedName) =>\n    i1.GeneratedColumn<bool>(\n      'active',\n      aliasedName,\n      false,\n      type: i1.DriftSqlType.bool,\n      defaultConstraints: i1.GeneratedColumn.constraintIsAlways(\n        'CHECK (\"active\" IN (0, 1))',\n      ),\n    );\ni1.GeneratedColumn<String> _column_3(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'name',\n      aliasedName,\n      false,\n      additionalChecks: i1.GeneratedColumn.checkTextLength(minTextLength: 1),\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<String> _column_4(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'url',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<DateTime> _column_5(String aliasedName) =>\n    i1.GeneratedColumn<DateTime>(\n      'last_update',\n      aliasedName,\n      false,\n      type: i1.DriftSqlType.dateTime,\n    );\ni1.GeneratedColumn<int> _column_6(String aliasedName) =>\n    i1.GeneratedColumn<int>(\n      'update_interval',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.int,\n    );\ni1.GeneratedColumn<int> _column_7(String aliasedName) =>\n    i1.GeneratedColumn<int>(\n      'upload',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.int,\n    );\ni1.GeneratedColumn<int> _column_8(String aliasedName) =>\n    i1.GeneratedColumn<int>(\n      'download',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.int,\n    );\ni1.GeneratedColumn<int> _column_9(String aliasedName) =>\n    i1.GeneratedColumn<int>(\n      'total',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.int,\n    );\ni1.GeneratedColumn<DateTime> _column_10(String aliasedName) =>\n    i1.GeneratedColumn<DateTime>(\n      'expire',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.dateTime,\n    );\ni1.GeneratedColumn<String> _column_11(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'web_page_url',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<String> _column_12(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'support_url',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.string,\n    );\n\nfinal class Schema3 extends i0.VersionedSchema {\n  Schema3({required super.database}) : super(version: 3);\n  @override\n  late final List<i1.DatabaseSchemaEntity> entities = [\n    profileEntries,\n    geoAssetEntries,\n  ];\n  late final Shape0 profileEntries = Shape0(\n    source: i0.VersionedTable(\n      entityName: 'profile_entries',\n      withoutRowId: false,\n      isStrict: false,\n      tableConstraints: ['PRIMARY KEY(id)'],\n      columns: [\n        _column_0,\n        _column_1,\n        _column_2,\n        _column_3,\n        _column_4,\n        _column_5,\n        _column_6,\n        _column_7,\n        _column_8,\n        _column_9,\n        _column_10,\n        _column_11,\n        _column_12,\n      ],\n      attachedDatabase: database,\n    ),\n    alias: null,\n  );\n  late final Shape1 geoAssetEntries = Shape1(\n    source: i0.VersionedTable(\n      entityName: 'geo_asset_entries',\n      withoutRowId: false,\n      isStrict: false,\n      tableConstraints: ['PRIMARY KEY(id)', 'UNIQUE(name, provider_name)'],\n      columns: [\n        _column_0,\n        _column_1,\n        _column_2,\n        _column_3,\n        _column_13,\n        _column_14,\n        _column_15,\n      ],\n      attachedDatabase: database,\n    ),\n    alias: null,\n  );\n}\n\nclass Shape1 extends i0.VersionedTable {\n  Shape1({required super.source, required super.alias}) : super.aliased();\n  i1.GeneratedColumn<String> get id =>\n      columnsByName['id']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get type =>\n      columnsByName['type']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<bool> get active =>\n      columnsByName['active']! as i1.GeneratedColumn<bool>;\n  i1.GeneratedColumn<String> get name =>\n      columnsByName['name']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get providerName =>\n      columnsByName['provider_name']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get version =>\n      columnsByName['version']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<DateTime> get lastCheck =>\n      columnsByName['last_check']! as i1.GeneratedColumn<DateTime>;\n}\n\ni1.GeneratedColumn<String> _column_13(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'provider_name',\n      aliasedName,\n      false,\n      additionalChecks: i1.GeneratedColumn.checkTextLength(minTextLength: 1),\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<String> _column_14(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'version',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<DateTime> _column_15(String aliasedName) =>\n    i1.GeneratedColumn<DateTime>(\n      'last_check',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.dateTime,\n    );\n\nfinal class Schema4 extends i0.VersionedSchema {\n  Schema4({required super.database}) : super(version: 4);\n  @override\n  late final List<i1.DatabaseSchemaEntity> entities = [\n    profileEntries,\n    geoAssetEntries,\n  ];\n  late final Shape2 profileEntries = Shape2(\n    source: i0.VersionedTable(\n      entityName: 'profile_entries',\n      withoutRowId: false,\n      isStrict: false,\n      tableConstraints: ['PRIMARY KEY(id)'],\n      columns: [\n        _column_0,\n        _column_1,\n        _column_2,\n        _column_3,\n        _column_4,\n        _column_5,\n        _column_6,\n        _column_7,\n        _column_8,\n        _column_9,\n        _column_10,\n        _column_11,\n        _column_12,\n        _column_16,\n      ],\n      attachedDatabase: database,\n    ),\n    alias: null,\n  );\n  late final Shape1 geoAssetEntries = Shape1(\n    source: i0.VersionedTable(\n      entityName: 'geo_asset_entries',\n      withoutRowId: false,\n      isStrict: false,\n      tableConstraints: ['PRIMARY KEY(id)', 'UNIQUE(name, provider_name)'],\n      columns: [\n        _column_0,\n        _column_1,\n        _column_2,\n        _column_3,\n        _column_13,\n        _column_14,\n        _column_15,\n      ],\n      attachedDatabase: database,\n    ),\n    alias: null,\n  );\n}\n\nclass Shape2 extends i0.VersionedTable {\n  Shape2({required super.source, required super.alias}) : super.aliased();\n  i1.GeneratedColumn<String> get id =>\n      columnsByName['id']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get type =>\n      columnsByName['type']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<bool> get active =>\n      columnsByName['active']! as i1.GeneratedColumn<bool>;\n  i1.GeneratedColumn<String> get name =>\n      columnsByName['name']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get url =>\n      columnsByName['url']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<DateTime> get lastUpdate =>\n      columnsByName['last_update']! as i1.GeneratedColumn<DateTime>;\n  i1.GeneratedColumn<int> get updateInterval =>\n      columnsByName['update_interval']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<int> get upload =>\n      columnsByName['upload']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<int> get download =>\n      columnsByName['download']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<int> get total =>\n      columnsByName['total']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<DateTime> get expire =>\n      columnsByName['expire']! as i1.GeneratedColumn<DateTime>;\n  i1.GeneratedColumn<String> get webPageUrl =>\n      columnsByName['web_page_url']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get supportUrl =>\n      columnsByName['support_url']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get testUrl =>\n      columnsByName['test_url']! as i1.GeneratedColumn<String>;\n}\n\ni1.GeneratedColumn<String> _column_16(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'test_url',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.string,\n    );\n\nfinal class Schema5 extends i0.VersionedSchema {\n  Schema5({required super.database}) : super(version: 5);\n  @override\n  late final List<i1.DatabaseSchemaEntity> entities = [\n    profileEntries,\n    appProxyEntries,\n  ];\n  late final Shape3 profileEntries = Shape3(\n    source: i0.VersionedTable(\n      entityName: 'profile_entries',\n      withoutRowId: false,\n      isStrict: false,\n      tableConstraints: ['PRIMARY KEY(id)'],\n      columns: [\n        _column_0,\n        _column_1,\n        _column_2,\n        _column_3,\n        _column_4,\n        _column_5,\n        _column_6,\n        _column_7,\n        _column_8,\n        _column_9,\n        _column_10,\n        _column_11,\n        _column_12,\n        _column_17,\n        _column_18,\n        _column_19,\n      ],\n      attachedDatabase: database,\n    ),\n    alias: null,\n  );\n  late final Shape4 appProxyEntries = Shape4(\n    source: i0.VersionedTable(\n      entityName: 'app_proxy_entries',\n      withoutRowId: false,\n      isStrict: false,\n      tableConstraints: ['PRIMARY KEY(mode, pkg_name)'],\n      columns: [_column_20, _column_21, _column_22],\n      attachedDatabase: database,\n    ),\n    alias: null,\n  );\n}\n\nclass Shape3 extends i0.VersionedTable {\n  Shape3({required super.source, required super.alias}) : super.aliased();\n  i1.GeneratedColumn<String> get id =>\n      columnsByName['id']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get type =>\n      columnsByName['type']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<bool> get active =>\n      columnsByName['active']! as i1.GeneratedColumn<bool>;\n  i1.GeneratedColumn<String> get name =>\n      columnsByName['name']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get url =>\n      columnsByName['url']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<DateTime> get lastUpdate =>\n      columnsByName['last_update']! as i1.GeneratedColumn<DateTime>;\n  i1.GeneratedColumn<int> get updateInterval =>\n      columnsByName['update_interval']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<int> get upload =>\n      columnsByName['upload']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<int> get download =>\n      columnsByName['download']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<int> get total =>\n      columnsByName['total']! as i1.GeneratedColumn<int>;\n  i1.GeneratedColumn<DateTime> get expire =>\n      columnsByName['expire']! as i1.GeneratedColumn<DateTime>;\n  i1.GeneratedColumn<String> get webPageUrl =>\n      columnsByName['web_page_url']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get supportUrl =>\n      columnsByName['support_url']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get populatedHeaders =>\n      columnsByName['populated_headers']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get profileOverride =>\n      columnsByName['profile_override']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get userOverride =>\n      columnsByName['user_override']! as i1.GeneratedColumn<String>;\n}\n\ni1.GeneratedColumn<String> _column_17(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'populated_headers',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<String> _column_18(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'profile_override',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<String> _column_19(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'user_override',\n      aliasedName,\n      true,\n      type: i1.DriftSqlType.string,\n    );\n\nclass Shape4 extends i0.VersionedTable {\n  Shape4({required super.source, required super.alias}) : super.aliased();\n  i1.GeneratedColumn<String> get mode =>\n      columnsByName['mode']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<String> get pkgName =>\n      columnsByName['pkg_name']! as i1.GeneratedColumn<String>;\n  i1.GeneratedColumn<int> get flags =>\n      columnsByName['flags']! as i1.GeneratedColumn<int>;\n}\n\ni1.GeneratedColumn<String> _column_20(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'mode',\n      aliasedName,\n      false,\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<String> _column_21(String aliasedName) =>\n    i1.GeneratedColumn<String>(\n      'pkg_name',\n      aliasedName,\n      false,\n      type: i1.DriftSqlType.string,\n    );\ni1.GeneratedColumn<int> _column_22(String aliasedName) =>\n    i1.GeneratedColumn<int>(\n      'flags',\n      aliasedName,\n      false,\n      type: i1.DriftSqlType.int,\n      defaultValue: const CustomExpression('0'),\n    );\ni0.MigrationStepWithVersion migrationSteps({\n  required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,\n  required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,\n  required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,\n  required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,\n}) {\n  return (currentVersion, database) async {\n    switch (currentVersion) {\n      case 1:\n        final schema = Schema2(database: database);\n        final migrator = i1.Migrator(database, schema);\n        await from1To2(migrator, schema);\n        return 2;\n      case 2:\n        final schema = Schema3(database: database);\n        final migrator = i1.Migrator(database, schema);\n        await from2To3(migrator, schema);\n        return 3;\n      case 3:\n        final schema = Schema4(database: database);\n        final migrator = i1.Migrator(database, schema);\n        await from3To4(migrator, schema);\n        return 4;\n      case 4:\n        final schema = Schema5(database: database);\n        final migrator = i1.Migrator(database, schema);\n        await from4To5(migrator, schema);\n        return 5;\n      default:\n        throw ArgumentError.value('Unknown migration from $currentVersion');\n    }\n  };\n}\n\ni1.OnUpgrade stepByStep({\n  required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,\n  required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,\n  required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,\n  required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,\n}) => i0.VersionedSchema.stepByStepHelper(\n  step: migrationSteps(\n    from1To2: from1To2,\n    from2To3: from2To3,\n    from3To4: from3To4,\n    from4To5: from4To5,\n  ),\n);\n"
  },
  {
    "path": "lib/core/db/provider/db_providers.dart",
    "content": "import 'package:hiddify/core/db/db.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'db_providers.g.dart';\n\n@Riverpod(keepAlive: true)\nDb db(Ref ref) => Db();\n"
  },
  {
    "path": "lib/core/db/schemas/db/drift_schema_v1.json",
    "content": "{\n    \"_meta\": {\n        \"description\": \"This file contains a serialized version of schema entities for drift.\",\n        \"version\": \"1.1.0\"\n    },\n    \"options\": {\n        \"store_date_time_values_as_text\": true\n    },\n    \"entities\": [\n        {\n            \"id\": 0,\n            \"references\": [],\n            \"type\": \"table\",\n            \"data\": {\n                \"name\": \"profile_entries\",\n                \"was_declared_in_moor\": false,\n                \"columns\": [\n                    {\n                        \"name\": \"id\",\n                        \"getter_name\": \"id\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"active\",\n                        \"getter_name\": \"active\",\n                        \"moor_type\": \"bool\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"defaultConstraints\": \"CHECK (\\\"active\\\" IN (0, 1))\",\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"name\",\n                        \"getter_name\": \"name\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [\n                            {\n                                \"allowed-lengths\": {\n                                    \"min\": 1,\n                                    \"max\": null\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        \"name\": \"url\",\n                        \"getter_name\": \"url\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"last_update\",\n                        \"getter_name\": \"lastUpdate\",\n                        \"moor_type\": \"dateTime\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"update_interval\",\n                        \"getter_name\": \"updateInterval\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [],\n                        \"type_converter\": {\n                            \"dart_expr\": \"DurationTypeConverter()\",\n                            \"dart_type_name\": \"Duration\"\n                        }\n                    },\n                    {\n                        \"name\": \"upload\",\n                        \"getter_name\": \"upload\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"download\",\n                        \"getter_name\": \"download\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"total\",\n                        \"getter_name\": \"total\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"expire\",\n                        \"getter_name\": \"expire\",\n                        \"moor_type\": \"dateTime\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"web_page_url\",\n                        \"getter_name\": \"webPageUrl\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"support_url\",\n                        \"getter_name\": \"supportUrl\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    }\n                ],\n                \"is_virtual\": false,\n                \"without_rowid\": false,\n                \"constraints\": [],\n                \"explicit_pk\": [\n                    \"id\"\n                ]\n            }\n        }\n    ]\n}"
  },
  {
    "path": "lib/core/db/schemas/db/drift_schema_v2.json",
    "content": "{\n    \"_meta\": {\n        \"description\": \"This file contains a serialized version of schema entities for drift.\",\n        \"version\": \"1.1.0\"\n    },\n    \"options\": {\n        \"store_date_time_values_as_text\": true\n    },\n    \"entities\": [\n        {\n            \"id\": 0,\n            \"references\": [],\n            \"type\": \"table\",\n            \"data\": {\n                \"name\": \"profile_entries\",\n                \"was_declared_in_moor\": false,\n                \"columns\": [\n                    {\n                        \"name\": \"id\",\n                        \"getter_name\": \"id\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"type\",\n                        \"getter_name\": \"type\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [],\n                        \"type_converter\": {\n                            \"dart_expr\": \"const EnumNameConverter<ProfileType>(ProfileType.values)\",\n                            \"dart_type_name\": \"ProfileType\"\n                        }\n                    },\n                    {\n                        \"name\": \"active\",\n                        \"getter_name\": \"active\",\n                        \"moor_type\": \"bool\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"defaultConstraints\": \"CHECK (\\\"active\\\" IN (0, 1))\",\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"name\",\n                        \"getter_name\": \"name\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [\n                            {\n                                \"allowed-lengths\": {\n                                    \"min\": 1,\n                                    \"max\": null\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        \"name\": \"url\",\n                        \"getter_name\": \"url\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"last_update\",\n                        \"getter_name\": \"lastUpdate\",\n                        \"moor_type\": \"dateTime\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"update_interval\",\n                        \"getter_name\": \"updateInterval\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [],\n                        \"type_converter\": {\n                            \"dart_expr\": \"DurationTypeConverter()\",\n                            \"dart_type_name\": \"Duration\"\n                        }\n                    },\n                    {\n                        \"name\": \"upload\",\n                        \"getter_name\": \"upload\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"download\",\n                        \"getter_name\": \"download\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"total\",\n                        \"getter_name\": \"total\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"expire\",\n                        \"getter_name\": \"expire\",\n                        \"moor_type\": \"dateTime\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"web_page_url\",\n                        \"getter_name\": \"webPageUrl\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"support_url\",\n                        \"getter_name\": \"supportUrl\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    }\n                ],\n                \"is_virtual\": false,\n                \"without_rowid\": false,\n                \"constraints\": [],\n                \"explicit_pk\": [\n                    \"id\"\n                ]\n            }\n        }\n    ]\n}"
  },
  {
    "path": "lib/core/db/schemas/db/drift_schema_v3.json",
    "content": "{\n    \"_meta\": {\n        \"description\": \"This file contains a serialized version of schema entities for drift.\",\n        \"version\": \"1.1.0\"\n    },\n    \"options\": {\n        \"store_date_time_values_as_text\": true\n    },\n    \"entities\": [\n        {\n            \"id\": 0,\n            \"references\": [],\n            \"type\": \"table\",\n            \"data\": {\n                \"name\": \"profile_entries\",\n                \"was_declared_in_moor\": false,\n                \"columns\": [\n                    {\n                        \"name\": \"id\",\n                        \"getter_name\": \"id\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"type\",\n                        \"getter_name\": \"type\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [],\n                        \"type_converter\": {\n                            \"dart_expr\": \"const EnumNameConverter<ProfileType>(ProfileType.values)\",\n                            \"dart_type_name\": \"ProfileType\"\n                        }\n                    },\n                    {\n                        \"name\": \"active\",\n                        \"getter_name\": \"active\",\n                        \"moor_type\": \"bool\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"defaultConstraints\": \"CHECK (\\\"active\\\" IN (0, 1))\",\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"name\",\n                        \"getter_name\": \"name\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [\n                            {\n                                \"allowed-lengths\": {\n                                    \"min\": 1,\n                                    \"max\": null\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        \"name\": \"url\",\n                        \"getter_name\": \"url\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"last_update\",\n                        \"getter_name\": \"lastUpdate\",\n                        \"moor_type\": \"dateTime\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"update_interval\",\n                        \"getter_name\": \"updateInterval\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [],\n                        \"type_converter\": {\n                            \"dart_expr\": \"DurationTypeConverter()\",\n                            \"dart_type_name\": \"Duration\"\n                        }\n                    },\n                    {\n                        \"name\": \"upload\",\n                        \"getter_name\": \"upload\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"download\",\n                        \"getter_name\": \"download\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"total\",\n                        \"getter_name\": \"total\",\n                        \"moor_type\": \"int\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"expire\",\n                        \"getter_name\": \"expire\",\n                        \"moor_type\": \"dateTime\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"web_page_url\",\n                        \"getter_name\": \"webPageUrl\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"support_url\",\n                        \"getter_name\": \"supportUrl\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    }\n                ],\n                \"is_virtual\": false,\n                \"without_rowid\": false,\n                \"constraints\": [],\n                \"explicit_pk\": [\n                    \"id\"\n                ]\n            }\n        },\n        {\n            \"id\": 1,\n            \"references\": [],\n            \"type\": \"table\",\n            \"data\": {\n                \"name\": \"geo_asset_entries\",\n                \"was_declared_in_moor\": false,\n                \"columns\": [\n                    {\n                        \"name\": \"id\",\n                        \"getter_name\": \"id\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"type\",\n                        \"getter_name\": \"type\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [],\n                        \"type_converter\": {\n                            \"dart_expr\": \"const EnumNameConverter<GeoAssetType>(GeoAssetType.values)\",\n                            \"dart_type_name\": \"GeoAssetType\"\n                        }\n                    },\n                    {\n                        \"name\": \"active\",\n                        \"getter_name\": \"active\",\n                        \"moor_type\": \"bool\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"defaultConstraints\": \"CHECK (\\\"active\\\" IN (0, 1))\",\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"name\",\n                        \"getter_name\": \"name\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [\n                            {\n                                \"allowed-lengths\": {\n                                    \"min\": 1,\n                                    \"max\": null\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        \"name\": \"provider_name\",\n                        \"getter_name\": \"providerName\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": false,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": [\n                            {\n                                \"allowed-lengths\": {\n                                    \"min\": 1,\n                                    \"max\": null\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        \"name\": \"version\",\n                        \"getter_name\": \"version\",\n                        \"moor_type\": \"string\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    },\n                    {\n                        \"name\": \"last_check\",\n                        \"getter_name\": \"lastCheck\",\n                        \"moor_type\": \"dateTime\",\n                        \"nullable\": true,\n                        \"customConstraints\": null,\n                        \"default_dart\": null,\n                        \"default_client_dart\": null,\n                        \"dsl_features\": []\n                    }\n                ],\n                \"is_virtual\": false,\n                \"without_rowid\": false,\n                \"constraints\": [],\n                \"explicit_pk\": [\n                    \"id\"\n                ],\n                \"unique_keys\": [\n                    [\n                        \"name\",\n                        \"provider_name\"\n                    ]\n                ]\n            }\n        }\n    ]\n}"
  },
  {
    "path": "lib/core/db/schemas/db/drift_schema_v4.json",
    "content": "{\"_meta\":{\"description\":\"This file contains a serialized version of schema entities for drift.\",\"version\":\"1.2.0\"},\"options\":{\"store_date_time_values_as_text\":true},\"entities\":[{\"id\":0,\"references\":[],\"type\":\"table\",\"data\":{\"name\":\"profile_entries\",\"was_declared_in_moor\":false,\"columns\":[{\"name\":\"id\",\"getter_name\":\"id\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"type\",\"getter_name\":\"type\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[],\"type_converter\":{\"dart_expr\":\"const EnumNameConverter<ProfileType>(ProfileType.values)\",\"dart_type_name\":\"ProfileType\"}},{\"name\":\"active\",\"getter_name\":\"active\",\"moor_type\":\"bool\",\"nullable\":false,\"customConstraints\":null,\"defaultConstraints\":\"CHECK (\\\"active\\\" IN (0, 1))\",\"dialectAwareDefaultConstraints\":{\"sqlite\":\"CHECK (\\\"active\\\" IN (0, 1))\"},\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"name\",\"getter_name\":\"name\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[{\"allowed-lengths\":{\"min\":1,\"max\":null}}]},{\"name\":\"url\",\"getter_name\":\"url\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"last_update\",\"getter_name\":\"lastUpdate\",\"moor_type\":\"dateTime\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"update_interval\",\"getter_name\":\"updateInterval\",\"moor_type\":\"int\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[],\"type_converter\":{\"dart_expr\":\"DurationTypeConverter()\",\"dart_type_name\":\"Duration\"}},{\"name\":\"upload\",\"getter_name\":\"upload\",\"moor_type\":\"int\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"download\",\"getter_name\":\"download\",\"moor_type\":\"int\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"total\",\"getter_name\":\"total\",\"moor_type\":\"int\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"expire\",\"getter_name\":\"expire\",\"moor_type\":\"dateTime\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"web_page_url\",\"getter_name\":\"webPageUrl\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"support_url\",\"getter_name\":\"supportUrl\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"test_url\",\"getter_name\":\"testUrl\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]}],\"is_virtual\":false,\"without_rowid\":false,\"constraints\":[],\"explicit_pk\":[\"id\"]}},{\"id\":1,\"references\":[],\"type\":\"table\",\"data\":{\"name\":\"geo_asset_entries\",\"was_declared_in_moor\":false,\"columns\":[{\"name\":\"id\",\"getter_name\":\"id\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"type\",\"getter_name\":\"type\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[],\"type_converter\":{\"dart_expr\":\"const EnumNameConverter<GeoAssetType>(GeoAssetType.values)\",\"dart_type_name\":\"GeoAssetType\"}},{\"name\":\"active\",\"getter_name\":\"active\",\"moor_type\":\"bool\",\"nullable\":false,\"customConstraints\":null,\"defaultConstraints\":\"CHECK (\\\"active\\\" IN (0, 1))\",\"dialectAwareDefaultConstraints\":{\"sqlite\":\"CHECK (\\\"active\\\" IN (0, 1))\"},\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"name\",\"getter_name\":\"name\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[{\"allowed-lengths\":{\"min\":1,\"max\":null}}]},{\"name\":\"provider_name\",\"getter_name\":\"providerName\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[{\"allowed-lengths\":{\"min\":1,\"max\":null}}]},{\"name\":\"version\",\"getter_name\":\"version\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"last_check\",\"getter_name\":\"lastCheck\",\"moor_type\":\"dateTime\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]}],\"is_virtual\":false,\"without_rowid\":false,\"constraints\":[],\"explicit_pk\":[\"id\"],\"unique_keys\":[[\"name\",\"provider_name\"]]}}]}"
  },
  {
    "path": "lib/core/db/schemas/db/drift_schema_v5.json",
    "content": "{\"_meta\":{\"description\":\"This file contains a serialized version of schema entities for drift.\",\"version\":\"1.2.0\"},\"options\":{\"store_date_time_values_as_text\":true},\"entities\":[{\"id\":0,\"references\":[],\"type\":\"table\",\"data\":{\"name\":\"profile_entries\",\"was_declared_in_moor\":false,\"columns\":[{\"name\":\"id\",\"getter_name\":\"id\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"type\",\"getter_name\":\"type\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[],\"type_converter\":{\"dart_expr\":\"const EnumNameConverter<ProfileType>(ProfileType.values)\",\"dart_type_name\":\"ProfileType\"}},{\"name\":\"active\",\"getter_name\":\"active\",\"moor_type\":\"bool\",\"nullable\":false,\"customConstraints\":null,\"defaultConstraints\":\"CHECK (\\\"active\\\" IN (0, 1))\",\"dialectAwareDefaultConstraints\":{\"sqlite\":\"CHECK (\\\"active\\\" IN (0, 1))\"},\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"name\",\"getter_name\":\"name\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[{\"allowed-lengths\":{\"min\":1,\"max\":null}}]},{\"name\":\"url\",\"getter_name\":\"url\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"last_update\",\"getter_name\":\"lastUpdate\",\"moor_type\":\"dateTime\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"update_interval\",\"getter_name\":\"updateInterval\",\"moor_type\":\"int\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[],\"type_converter\":{\"dart_expr\":\"DurationTypeConverter()\",\"dart_type_name\":\"Duration\"}},{\"name\":\"upload\",\"getter_name\":\"upload\",\"moor_type\":\"int\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"download\",\"getter_name\":\"download\",\"moor_type\":\"int\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"total\",\"getter_name\":\"total\",\"moor_type\":\"int\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"expire\",\"getter_name\":\"expire\",\"moor_type\":\"dateTime\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"web_page_url\",\"getter_name\":\"webPageUrl\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"support_url\",\"getter_name\":\"supportUrl\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"populated_headers\",\"getter_name\":\"populatedHeaders\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"profile_override\",\"getter_name\":\"profileOverride\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"user_override\",\"getter_name\":\"userOverride\",\"moor_type\":\"string\",\"nullable\":true,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]}],\"is_virtual\":false,\"without_rowid\":false,\"constraints\":[],\"explicit_pk\":[\"id\"]}},{\"id\":1,\"references\":[],\"type\":\"table\",\"data\":{\"name\":\"app_proxy_entries\",\"was_declared_in_moor\":false,\"columns\":[{\"name\":\"mode\",\"getter_name\":\"mode\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[],\"type_converter\":{\"dart_expr\":\"const EnumNameConverter<AppProxyMode>(AppProxyMode.values)\",\"dart_type_name\":\"AppProxyMode\"}},{\"name\":\"pkg_name\",\"getter_name\":\"pkgName\",\"moor_type\":\"string\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":null,\"default_client_dart\":null,\"dsl_features\":[]},{\"name\":\"flags\",\"getter_name\":\"flags\",\"moor_type\":\"int\",\"nullable\":false,\"customConstraints\":null,\"default_dart\":\"const CustomExpression('0')\",\"default_client_dart\":null,\"dsl_features\":[]}],\"is_virtual\":false,\"without_rowid\":false,\"constraints\":[],\"explicit_pk\":[\"mode\",\"pkg_name\"]}}]}"
  },
  {
    "path": "lib/core/directories/directories_provider.dart",
    "content": "import 'dart:io';\n\nimport 'package:flutter/foundation.dart' show kIsWeb;\nimport 'package:flutter/services.dart';\nimport 'package:hiddify/core/model/directories.dart';\nimport 'package:hiddify/core/model/environment.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hiddify/utils/platform_utils.dart';\nimport 'package:path/path.dart' as p;\nimport 'package:path_provider/path_provider.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'directories_provider.g.dart';\n\n@Riverpod(keepAlive: true)\nclass AppDirectories extends _$AppDirectories with InfraLogger {\n  final _methodChannel = const MethodChannel(\"com.hiddify.app/platform\");\n\n  @override\n  Future<Directories> build() async {\n    final Directories dirs;\n    if (kIsWeb) {\n      return (baseDir: Directory(\".\"), workingDir: Directory(\".\"), tempDir: Directory(\".\"));\n    }\n    if (PlatformUtils.isIOS) {\n      final paths = await _methodChannel.invokeMethod<Map>(\"get_paths\");\n      loggy.debug(\"paths: $paths\");\n      dirs = (\n        baseDir: Directory(paths?[\"base\"]! as String),\n        workingDir: Directory(paths?[\"working\"]! as String),\n        tempDir: Directory(paths?[\"temp\"]! as String),\n      );\n    } else if (PlatformUtils.isWindows &&\n        Environment.isPortable &&\n        await checkDirectoryAccess(getPortableDirectory())) {\n      final portableDir = getPortableDirectory();\n      dirs = (baseDir: portableDir, workingDir: portableDir, tempDir: await getTemporaryDirectory());\n    } else {\n      final baseDir = await getApplicationSupportDirectory();\n      final workingDir = Platform.isAndroid ? await getExternalStorageDirectory() : baseDir;\n      final tempDir = await getTemporaryDirectory();\n      dirs = (baseDir: baseDir, workingDir: workingDir!, tempDir: tempDir);\n    }\n\n    if (!dirs.baseDir.existsSync()) {\n      await dirs.baseDir.create(recursive: true);\n    }\n    if (!dirs.workingDir.existsSync()) {\n      await dirs.workingDir.create(recursive: true);\n    }\n\n    return dirs;\n  }\n\n  static Future<Directory> getDatabaseDirectory() async {\n    if (kIsWeb) {\n      return Directory(\".\");\n    }\n    if (PlatformUtils.isIOS || PlatformUtils.isMacOS) {\n      return await getLibraryDirectory();\n    } else if (PlatformUtils.isWindows &&\n        Environment.isPortable &&\n        await checkDirectoryAccess(getPortableDirectory())) {\n      final portableDir = getPortableDirectory();\n      return portableDir;\n    } else if (PlatformUtils.isWindows || PlatformUtils.isLinux) {\n      return await getApplicationSupportDirectory();\n    }\n    return await getApplicationDocumentsDirectory();\n  }\n\n  static Directory getPortableDirectory() {\n    final exeDir = File(Platform.resolvedExecutable).parent;\n    return Directory(p.join(exeDir.path, 'hiddify_portable_data'));\n  }\n\n  static Future<bool> checkDirectoryAccess(Directory dir) async {\n    final testFile = File(p.join(dir.path, 'access_test.txt'));\n\n    try {\n      if (!await dir.exists()) await dir.create(recursive: true);\n      await testFile.writeAsString('Testing write permission...');\n      await testFile.readAsString();\n      await testFile.delete();\n      return true;\n    } catch (_) {\n      return false;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/core/haptic/haptic_service.dart",
    "content": "import 'package:flutter/services.dart';\nimport 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\npart 'haptic_service.g.dart';\n\n@Riverpod(keepAlive: true)\nclass HapticService extends _$HapticService {\n  @override\n  bool build() {\n    return _preferences.getBool(hapticFeedbackPrefKey) ?? true;\n  }\n\n  static const String hapticFeedbackPrefKey = \"haptic_feedback\";\n  SharedPreferences get _preferences => ref.read(sharedPreferencesProvider).requireValue;\n\n  Future<void> updatePreference(bool value) async {\n    state = value;\n    await _preferences.setBool(hapticFeedbackPrefKey, value);\n  }\n\n  Future<void> lightImpact() async {\n    if (state) {\n      await HapticFeedback.lightImpact();\n    }\n  }\n\n  Future<void> mediumImpact() async {\n    if (state) {\n      await HapticFeedback.mediumImpact();\n    }\n  }\n\n  Future<void> heavyImpact() async {\n    if (state) {\n      await HapticFeedback.heavyImpact();\n    }\n  }\n}\n"
  },
  {
    "path": "lib/core/http_client/dio_http_client.dart",
    "content": "import 'dart:convert';\nimport 'dart:io';\n\nimport 'package:dio/dio.dart';\nimport 'package:dio/io.dart';\nimport 'package:dio_smart_retry/dio_smart_retry.dart';\n\nimport 'package:hiddify/utils/custom_loggers.dart';\n\nclass DioHttpClient with InfraLogger {\n  final Map<String, Dio> _dio = {};\n  DioHttpClient({required Duration timeout, required this.userAgent, required bool debug}) {\n    for (var mode in [\"proxy\", \"direct\", \"both\"]) {\n      _dio[mode] = Dio(\n        BaseOptions(\n          connectTimeout: timeout,\n          sendTimeout: timeout,\n          receiveTimeout: timeout,\n          headers: {\"User-Agent\": userAgent},\n        ),\n      );\n      _dio[mode]!.interceptors.add(\n        RetryInterceptor(\n          dio: _dio[mode]!,\n          retryDelays: [\n            const Duration(seconds: 1),\n            if (mode != \"proxy\") ...[const Duration(seconds: 2), const Duration(seconds: 3)],\n          ],\n        ),\n      );\n\n      _dio[mode]!.httpClientAdapter = IOHttpClientAdapter(\n        createHttpClient: () {\n          final client = HttpClient();\n          client.findProxy = (url) {\n            if (mode == \"proxy\") {\n              return \"PROXY localhost:$port\";\n            } else if (mode == \"direct\") {\n              return \"DIRECT\";\n            } else {\n              return \"PROXY localhost:$port; DIRECT\";\n            }\n          };\n          return client;\n        },\n      );\n    }\n\n    if (debug) {\n      // _dio.interceptors.add(LoggyDioInterceptor(requestHeader: true));\n    }\n  }\n\n  int port = 0;\n\n  String userAgent;\n  // bool isPortOpen(String host, int port, {Duration timeout = const Duration(milliseconds: 200)}) async{\n  //   try {\n  //     Socket.connect(host, port, timeout: timeout).then((socket) {\n  //       socket.destroy();\n  //     });\n  //     return true;\n  //   } on SocketException catch (_) {\n  //     return false;\n  //   } catch (_) {\n  //     return false;\n  //   }\n  // }\n  Future<bool> isPortOpen(String host, int port, {Duration timeout = const Duration(seconds: 5)}) async {\n    try {\n      final socket = await Socket.connect(host, port, timeout: timeout);\n      await socket.close();\n      return true;\n    } on SocketException catch (_) {\n      return false;\n    } catch (_) {\n      return false;\n    }\n  }\n\n  void setProxyPort(int port) {\n    this.port = port;\n    loggy.debug(\"setting proxy port: [$port]\");\n  }\n\n  Future<Response<T>> get<T>(\n    String url, {\n    CancelToken? cancelToken,\n    String? userAgent,\n    ({String username, String password})? credentials,\n    bool proxyOnly = false,\n  }) async {\n    final mode = proxyOnly\n        ? \"proxy\"\n        : await isPortOpen(\"127.0.0.1\", port)\n        ? \"both\"\n        : \"direct\";\n    final dio = _dio[mode]!;\n\n    return dio.get<T>(\n      url,\n      cancelToken: cancelToken,\n      options: _options(url, userAgent: userAgent, credentials: credentials),\n    );\n  }\n\n  Future<Response> download(\n    String url,\n    String path, {\n    CancelToken? cancelToken,\n    String? userAgent,\n    ({String username, String password})? credentials,\n    bool proxyOnly = false,\n  }) async {\n    final mode = proxyOnly\n        ? \"proxy\"\n        : await isPortOpen(\"127.0.0.1\", port)\n        ? \"both\"\n        : \"direct\";\n    final dio = _dio[mode]!;\n    return dio.download(\n      url,\n      path,\n      cancelToken: cancelToken,\n      options: _options(url, userAgent: userAgent, credentials: credentials),\n    );\n  }\n\n  Options _options(String url, {String? userAgent, ({String username, String password})? credentials}) {\n    final uri = Uri.parse(url);\n\n    String? userInfo;\n    if (credentials != null) {\n      userInfo = \"${credentials.username}:${credentials.password}\";\n    } else if (uri.userInfo.isNotEmpty) {\n      userInfo = uri.userInfo;\n    }\n\n    String? basicAuth;\n    if (userInfo != null) {\n      basicAuth = \"Basic ${base64.encode(utf8.encode(userInfo))}\";\n    }\n\n    return Options(\n      headers: {\n        if (userAgent != null) \"User-Agent\": userAgent,\n        if (basicAuth != null) \"authorization\": basicAuth,\n        // \"Accept\": \"application/json\",\n        // \"Content-Type\": \"application/json\",\n      },\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/http_client/http_client_provider.dart",
    "content": "import 'package:flutter/foundation.dart';\nimport 'package:hiddify/core/app_info/app_info_provider.dart';\nimport 'package:hiddify/core/http_client/dio_http_client.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'http_client_provider.g.dart';\n\n@Riverpod(keepAlive: true)\nDioHttpClient httpClient(Ref ref) {\n  final client = DioHttpClient(\n    timeout: const Duration(seconds: 15),\n    userAgent: ref.watch(appInfoProvider).requireValue.userAgent,\n    debug: kDebugMode,\n  );\n\n  ref.listen(ConfigOptions.mixedPort, (_, next) => client.setProxyPort(next), fireImmediately: true);\n  return client;\n}\n"
  },
  {
    "path": "lib/core/localization/locale_extensions.dart",
    "content": "import 'dart:io';\n\nimport 'package:flutter/foundation.dart';\nimport 'package:hiddify/gen/fonts.gen.dart';\nimport 'package:hiddify/gen/translations.g.dart';\n\nextension AppLocaleX on AppLocale {\n  String get preferredFontFamily =>\n      this == AppLocale.fa ? FontFamily.shabnam : (kIsWeb || !Platform.isWindows ? \"\" : FontFamily.emoji);\n\n  String get localeName => switch (flutterLocale.toString()) {\n    \"ar\" => \"العربية\",\n    \"en\" => \"English\",\n    \"es\" => \"Spanish\",\n    \"fa\" => \"فارسی\",\n    \"fr\" => \"Français\",\n    \"id\" => \"Indonesian\",\n    \"pt_BR\" => \"Portuguese (Brazil)\",\n    \"ru\" => \"Русский\",\n    \"tr\" => \"Türkçe\",\n    \"zh\" || \"zh_CN\" => \"中文 (中国)\",\n    \"zh_TW\" => \"中文 (台湾)\",\n    _ => \"Unknown\",\n  };\n}\n"
  },
  {
    "path": "lib/core/localization/locale_preferences.dart",
    "content": "import 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/gen/translations.g.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'locale_preferences.g.dart';\n\n@Riverpod(keepAlive: true)\nclass LocalePreferences extends _$LocalePreferences with AppLogger {\n  @override\n  AppLocale build() {\n    final persisted = ref.watch(sharedPreferencesProvider).requireValue.getString(\"locale\");\n    if (persisted == null) return AppLocaleUtils.findDeviceLocale();\n    // keep backward compatibility with chinese after changing zh to zh_CN\n    if (persisted == \"zh\") {\n      return AppLocale.zhCn;\n    }\n    try {\n      return AppLocale.values.byName(persisted);\n    } catch (e) {\n      loggy.error(\"error setting locale: [$persisted]\", e);\n      return AppLocale.en;\n    }\n  }\n\n  Future<void> changeLocale(AppLocale value) async {\n    state = value;\n    await ref.read(sharedPreferencesProvider).requireValue.setString(\"locale\", value.name);\n  }\n}\n"
  },
  {
    "path": "lib/core/localization/translations.dart",
    "content": "import 'package:hiddify/core/localization/locale_preferences.dart';\nimport 'package:hiddify/gen/translations.g.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\nexport 'package:hiddify/gen/translations.g.dart';\n\npart 'translations.g.dart';\n\n@Riverpod(keepAlive: true)\nFuture<Translations> translations(Ref ref) async {\n  return await ref.watch(localePreferencesProvider).build();\n}\n"
  },
  {
    "path": "lib/core/logger/custom_logger.dart",
    "content": "// ignore_for_file: avoid_print\n\nimport 'dart:io';\n\nimport 'package:loggy/loggy.dart';\n\nclass ConsolePrinter extends LoggyPrinter {\n  const ConsolePrinter({this.showColors = false});\n\n  final bool showColors;\n\n  static final _levelColors = {\n    LogLevel.debug: AnsiColor(foregroundColor: AnsiColor.grey(0.5), italic: true),\n    LogLevel.info: AnsiColor(foregroundColor: 35),\n    LogLevel.warning: AnsiColor(foregroundColor: 214),\n    LogLevel.error: AnsiColor(foregroundColor: 196),\n  };\n\n  @override\n  void onLog(LogRecord record) {\n    final colorize = showColors && stdout.supportsAnsiEscapes;\n    final time = record.time.toIso8601String().split('T')[1];\n    final callerFrame = record.callerFrame == null ? ' ' : ' (${record.callerFrame?.location}) ';\n\n    final String logLevel;\n    if (colorize) {\n      logLevel = record.level.name.toUpperCase().padRight(8);\n    } else {\n      logLevel = \"[${record.level.name.toUpperCase()}]\".padRight(10);\n    }\n\n    final color = showColors ? levelColor(record.level) ?? AnsiColor() : AnsiColor();\n\n    print(color('$time $logLevel [${record.loggerName}]$callerFrame${record.message}'));\n\n    if (record.stackTrace != null) {\n      print(record.stackTrace);\n    }\n  }\n\n  AnsiColor? levelColor(LogLevel level) {\n    return _levelColors[level];\n  }\n}\n\nclass FileLogPrinter extends LoggyPrinter {\n  FileLogPrinter(String filePath, {this.minLevel = LogLevel.debug}) : _logFile = File(filePath);\n\n  final File _logFile;\n  final LogLevel minLevel;\n\n  late final _sink = _logFile.openWrite(mode: FileMode.writeOnly);\n\n  @override\n  void onLog(LogRecord record) {\n    final time = record.time.toIso8601String().split('T')[1];\n    _sink.writeln(\"$time - $record\");\n    if (record.error != null) {\n      _sink.writeln(record.error);\n    }\n    if (record.stackTrace != null) {\n      _sink.writeln(record.stackTrace);\n    }\n  }\n\n  void dispose() {\n    _sink.close();\n  }\n}\n"
  },
  {
    "path": "lib/core/logger/logger.dart",
    "content": "import 'package:flutter/foundation.dart';\nimport 'package:loggy/loggy.dart';\n\nclass Logger {\n  static final app = Loggy(\"app\");\n  static final bootstrap = Loggy(\"bootstrap\");\n\n  static void logFlutterError(FlutterErrorDetails details) {\n    if (details.silent) {\n      return;\n    }\n\n    final description = details.exceptionAsString();\n\n    app.error('Flutter Error: $description', details.exception, details.stack);\n  }\n\n  static bool logPlatformDispatcherError(Object error, StackTrace stackTrace) {\n    app.error('PlatformDispatcherError: $error', error, stackTrace);\n    return true;\n  }\n}\n"
  },
  {
    "path": "lib/core/logger/logger_controller.dart",
    "content": "import 'dart:io';\n\nimport 'package:hiddify/core/logger/custom_logger.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:loggy/loggy.dart';\nimport 'package:flutter/foundation.dart' show kIsWeb;\n\nclass LoggerController extends LoggyPrinter with InfraLogger {\n  LoggerController(this.consolePrinter, this.otherPrinters);\n\n  final LoggyPrinter consolePrinter;\n  final Map<String, LoggyPrinter> otherPrinters;\n\n  static LoggerController get instance => _instance;\n\n  static late LoggerController _instance;\n\n  static void preInit() {\n    Loggy.initLoggy(logPrinter: const ConsolePrinter());\n  }\n\n  static void init(String appLogPath) {\n    _instance = LoggerController(const ConsolePrinter(), {\"app\": kIsWeb ? const ConsolePrinter() : FileLogPrinter(appLogPath)});\n    Loggy.initLoggy(logPrinter: _instance);\n  }\n\n  static Future<void> postInit(bool debugMode) async {\n    final logLevel = debugMode && false ? LogLevel.all : LogLevel.info;\n    final logToFile = debugMode || (!Platform.isAndroid && !Platform.isIOS);\n\n    if (!logToFile || kIsWeb) _instance.removePrinter(\"app\");\n\n    Loggy.initLoggy(logPrinter: _instance, logOptions: LogOptions(logLevel));\n  }\n\n  void addPrinter(String name, LoggyPrinter printer) {\n    loggy.debug(\"adding [$name] printer\");\n    otherPrinters.putIfAbsent(name, () => printer);\n  }\n\n  void removePrinter(String name) {\n    loggy.debug(\"removing [$name] printer\");\n    final printer = otherPrinters[name];\n    if (printer case FileLogPrinter()) {\n      printer.dispose();\n    }\n    otherPrinters.remove(name);\n  }\n\n  @override\n  void onLog(LogRecord record) {\n    consolePrinter.onLog(record);\n    for (final printer in otherPrinters.values) {\n      printer.onLog(record);\n    }\n  }\n}\n"
  },
  {
    "path": "lib/core/model/app_info_entity.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/model/environment.dart';\n\npart 'app_info_entity.freezed.dart';\n\n@freezed\nclass AppInfoEntity with _$AppInfoEntity {\n  const AppInfoEntity._();\n\n  const factory AppInfoEntity({\n    required String name,\n    required String version,\n    required String buildNumber,\n    required Release release,\n    required String operatingSystem,\n    required String operatingSystemVersion,\n    required Environment environment,\n  }) = _AppInfoEntity;\n\n  String get userAgent => \"HiddifyNext/$version ($operatingSystem) like ClashMeta v2ray sing-box\";\n\n  String get presentVersion => environment == Environment.prod ? version : \"$version ${environment.name}\";\n\n  /// formats app info for sharing\n  String format() =>\n      '''\n$name v$version ($buildNumber) [${environment.name}]\n${release.name} release\n$operatingSystem [$operatingSystemVersion]''';\n}\n"
  },
  {
    "path": "lib/core/model/constants.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\n\nabstract class Constants {\n  static const appName = \"Hiddify\";\n  static const githubUrl = \"https://github.com/hiddify/hiddify-next\";\n  static const licenseUrl = \"https://github.com/hiddify/hiddify-next?tab=License-1-ov-file#readme\";\n  static const githubReleasesApiUrl = \"https://api.github.com/repos/hiddify/hiddify-next/releases\";\n  static const githubLatestReleaseUrl = \"https://github.com/hiddify/hiddify-app/releases/latest\";\n  static const appCastUrl = \"https://raw.githubusercontent.com/hiddify/hiddify-next/main/appcast.xml\";\n  static const telegramChannelUrl = \"https://t.me/hiddify\";\n  static const privacyPolicyUrl = \"https://hiddify.com/privacy-policy/\";\n  static const termsAndConditionsUrl = \"https://hiddify.com/terms/\";\n  static const cfWarpPrivacyPolicy = \"https://www.cloudflare.com/application/privacypolicy/\";\n  static const cfWarpTermsOfService = \"https://www.cloudflare.com/application/terms/\";\n}\n\nconst kAnimationDuration = Duration(milliseconds: 250);\n\nabstract class AddProfileModalConst {\n  static const fixBtnsGap = 16.0;\n  static const fixBtnsGapCount = 4;\n  static const fixBtnsItemCount = 3;\n  static const navBarGap = 16.0;\n  static const navBarBottomGap = 4.0;\n  //switch default height\n  static const navBarcontentHeight = 32.0;\n  static const navBarHeight = navBarGap + navBarBottomGap + navBarcontentHeight;\n}\n\nabstract class AlertDialogConst {\n  static const minWidth = 280.0;\n  static const maxWidth = 560.0;\n  static const boxConstraints = BoxConstraints(minWidth: minWidth, maxWidth: maxWidth);\n}\n\nabstract class BottomSheetConst {\n  static const maxWidth = 456.0;\n  static const boxConstraints = BoxConstraints(maxWidth: maxWidth);\n  static const borderRadius = BorderRadius.vertical(top: Radius.circular(32));\n}\n\nabstract class ProfileTileConst {\n  static const radius = Radius.circular(16);\n  static const cardBorderRadius = BorderRadius.all(radius);\n  static const borderRadiusRight = BorderRadius.horizontal(right: radius);\n  static const borderRadiusLeft = BorderRadius.horizontal(left: radius);\n  static BorderRadius startBorderRadius(TextDirection direction) =>\n      direction == TextDirection.ltr ? borderRadiusLeft : borderRadiusRight;\n  static BorderRadius endBorderRadius(TextDirection direction) =>\n      direction == TextDirection.ltr ? borderRadiusRight : borderRadiusLeft;\n}\n\nabstract class IntroConst {\n  static const maxwidth = 620;\n  static const termsAndConditionsKey = 'terms-and-conditions';\n  static const githubKey = 'github';\n  static const licenseKey = 'license';\n  static const url = <String, String>{IntroConst.termsAndConditionsKey: Constants.termsAndConditionsUrl, IntroConst.githubKey: Constants.githubUrl, IntroConst.licenseKey: Constants.licenseUrl};\n}\n\nabstract class WarpConst {\n  static const warpAccountId = 'warp-account-id';\n  static const warpAccessToken = \"warp-access-token\";\n  static const warpConsentGiven = \"warp-consent-given\";\n  static const warpTermsOfServiceKey = 'warp-terms-of-service';\n  static const warpPrivacyPolicyKey = 'warp-privacy-policy';\n  static const url = <String, String>{WarpConst.warpTermsOfServiceKey: Constants.cfWarpTermsOfService, WarpConst.warpPrivacyPolicyKey: Constants.cfWarpPrivacyPolicy};\n}\n\nabstract class KeyboardConst {\n  static final allArrows = {LogicalKeyboardKey.arrowUp, LogicalKeyboardKey.arrowDown, LogicalKeyboardKey.arrowLeft, LogicalKeyboardKey.arrowRight};\n  static final horizontalArrows = {LogicalKeyboardKey.arrowLeft, LogicalKeyboardKey.arrowRight};\n  static final verticalArrows = {LogicalKeyboardKey.arrowUp, LogicalKeyboardKey.arrowDown};\n  static final select = {LogicalKeyboardKey.select, LogicalKeyboardKey.enter, LogicalKeyboardKey.tab};\n}\n"
  },
  {
    "path": "lib/core/model/directories.dart",
    "content": "import 'dart:io';\n\ntypedef Directories = ({Directory baseDir, Directory workingDir, Directory tempDir});\n"
  },
  {
    "path": "lib/core/model/environment.dart",
    "content": "import 'package:dartx/dartx.dart';\n\nenum Environment {\n  prod,\n  dev;\n\n  static const sentryDSN = String.fromEnvironment(\"sentry_dsn\");\n  // This environment variable is set in the 'windows-release-zip' command\n  static const isPortable = bool.fromEnvironment(\"portable\");\n}\n\nenum Release {\n  general(\"general\"),\n  // This environment variable is set in the 'android-release-aab' command\n  googlePlay(\"google-play\");\n\n  const Release(this.key);\n\n  final String key;\n\n  bool get allowCustomUpdateChecker => this == general;\n\n  static Release read() =>\n      Release.values.firstOrNullWhere((e) => e.key == const String.fromEnvironment(\"release\")) ?? Release.general;\n}\n"
  },
  {
    "path": "lib/core/model/failures.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:grpc/grpc.dart';\nimport 'package:hiddify/core/localization/translations.dart';\n\ntypedef PresentableError = ({String type, String? message});\n\nmixin Failure {\n  ({String type, String? message}) present(TranslationsEn t);\n}\n\n/// failures that are not expected to happen but depending on [error] type might not be relevant (eg network errors)\nmixin UnexpectedFailure {\n  Object? get error;\n  StackTrace? get stackTrace;\n}\n\n/// failures that are expected to happen and should be handled by the app\n/// and should be logged, eg missing permissions\nmixin ExpectedMeasuredFailure {}\n\n/// failures ignored by analytics service etc.\nmixin ExpectedFailure {}\n\nextension ErrorPresenter on TranslationsEn {\n  PresentableError errorToPair(Object error) => switch (error) {\n    GrpcError(message: final nestedErr?) => errorToPair(nestedErr),\n    UnexpectedFailure(error: final nestedErr?) => errorToPair(nestedErr),\n    Failure() => error.present(this),\n    DioException() => error.present(this),\n    _ => (type: errors.unexpected, message: error.toString()),\n  };\n\n  PresentableError presentError(Object error, {String? action}) {\n    final pair = errorToPair(error);\n    if (action == null) return pair;\n    return (type: action, message: pair.type + (pair.message == null ? \"\" : \"\\n${pair.message!}\"));\n  }\n\n  String presentShortError(Object error, {String? action}) {\n    final pair = errorToPair(error);\n    if (action == null) return pair.type;\n    return \"$action: ${pair.type}\";\n  }\n}\n\nextension DioExceptionPresenter on DioException {\n  PresentableError present(TranslationsEn t) => switch (type) {\n    DioExceptionType.connectionTimeout ||\n    DioExceptionType.sendTimeout ||\n    DioExceptionType.receiveTimeout => (type: t.errors.connection.timeout, message: null),\n    DioExceptionType.badCertificate => (type: t.errors.connection.badCertificate, message: message),\n    DioExceptionType.badResponse => (type: t.errors.connection.badResponse, message: message),\n    DioExceptionType.connectionError => (type: t.errors.connection.connectionError, message: message),\n    _ => (type: t.errors.connection.unexpected, message: message),\n  };\n}\n"
  },
  {
    "path": "lib/core/model/optional_range.dart",
    "content": "import 'package:dart_mappable/dart_mappable.dart';\nimport 'package:dartx/dartx.dart';\nimport 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\n\npart 'optional_range.mapper.dart';\n\n@MappableClass()\nclass OptionalRange with OptionalRangeMappable {\n  const OptionalRange({this.min, this.max});\n\n  final int? min;\n  final int? max;\n\n  String format() => [min, max].whereNotNull().join(\"-\");\n  String present(TranslationsEn t) => format().isEmpty ? t.common.notSet : format();\n\n  factory OptionalRange.parse(String input, {bool allowEmpty = false}) => switch (input.split(\"-\")) {\n    [final String val] when val.isEmpty && allowEmpty => const OptionalRange(),\n    [final String min] => OptionalRange(min: int.parse(min)),\n    [final String min, final String max] => OptionalRange(min: int.parse(min), max: int.parse(max)),\n    _ => throw Exception(\"Invalid range: $input\"),\n  };\n\n  static OptionalRange? tryParse(String input, {bool allowEmpty = false}) {\n    try {\n      return OptionalRange.parse(input, allowEmpty: allowEmpty);\n    } catch (_) {\n      return null;\n    }\n  }\n}\n\nclass OptionalRangeJsonConverter implements JsonConverter<OptionalRange, String> {\n  const OptionalRangeJsonConverter();\n\n  @override\n  OptionalRange fromJson(String json) => OptionalRange.parse(json, allowEmpty: true);\n\n  @override\n  String toJson(OptionalRange object) => object.format();\n}\n"
  },
  {
    "path": "lib/core/model/region.dart",
    "content": "import 'package:hiddify/core/localization/translations.dart';\n\nenum Region {\n  ir,\n  cn,\n  ru,\n  af,\n  id,\n  tr,\n  br,\n  other;\n\n  String present(TranslationsEn t) => switch (this) {\n    ir => t.pages.settings.routing.regions.ir,\n    cn => t.pages.settings.routing.regions.cn,\n    ru => t.pages.settings.routing.regions.ru,\n    af => t.pages.settings.routing.regions.af,\n    id => t.pages.settings.routing.regions.id,\n    tr => t.pages.settings.routing.regions.tr,\n    br => t.pages.settings.routing.regions.br,\n    other => t.pages.settings.routing.regions.other,\n  };\n}\n"
  },
  {
    "path": "lib/core/notification/in_app_notification_controller.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:toastification/toastification.dart';\n\npart 'in_app_notification_controller.g.dart';\n\n@Riverpod(keepAlive: true)\nInAppNotificationController inAppNotificationController(Ref ref) {\n  return InAppNotificationController();\n}\n\nenum NotificationType { info, error, success }\n\nclass InAppNotificationController with AppLogger {\n  ToastificationItem _show(\n    String message, {\n    NotificationType type = NotificationType.info,\n    Duration duration = const Duration(seconds: 3),\n  }) {\n    toastification.dismissAll();\n    return toastification.show(\n      title: Text(message),\n      type: type._toastificationType,\n      alignment: AlignmentDirectional.bottomStart,\n      autoCloseDuration: duration,\n      style: ToastificationStyle.fillColored,\n      pauseOnHover: true,\n      showProgressBar: false,\n      dragToClose: true,\n      closeOnClick: true,\n      closeButtonShowType: CloseButtonShowType.onHover,\n    );\n  }\n\n  ToastificationItem? showErrorToast(String message) =>\n      _show(message, type: NotificationType.error, duration: const Duration(seconds: 5));\n\n  ToastificationItem? showSuccessToast(String message) => _show(message, type: NotificationType.success);\n\n  ToastificationItem? showInfoToast(String message, {Duration duration = const Duration(seconds: 3)}) =>\n      _show(message, duration: duration);\n}\n\nextension NotificationTypeX on NotificationType {\n  ToastificationType get _toastificationType => switch (this) {\n    NotificationType.success => ToastificationType.success,\n    NotificationType.error => ToastificationType.error,\n    NotificationType.info => ToastificationType.info,\n  };\n}\n"
  },
  {
    "path": "lib/core/preferences/actions_at_closing.dart",
    "content": "import 'package:hiddify/gen/translations.g.dart';\n\nenum ActionsAtClosing {\n  ask,\n  hide,\n  exit;\n\n  String present(TranslationsEn t) => switch (this) {\n    ask => t.dialogs.windowClosing.askEachTime,\n    hide => t.common.hide,\n    exit => t.common.exit,\n  };\n}\n"
  },
  {
    "path": "lib/core/preferences/general_preferences.dart",
    "content": "import 'package:flutter/foundation.dart';\nimport 'package:flutter/material.dart';\nimport 'package:hiddify/core/app_info/app_info_provider.dart';\nimport 'package:hiddify/core/model/environment.dart';\nimport 'package:hiddify/core/model/region.dart';\nimport 'package:hiddify/core/preferences/actions_at_closing.dart';\n\nimport 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/core/utils/preferences_utils.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_mode.dart';\nimport 'package:hiddify/features/window/notifier/window_notifier.dart';\nimport 'package:hiddify/utils/platform_utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'general_preferences.g.dart';\n\nbool _debugIntroPage = false;\n\nabstract class Preferences {\n  static final introCompleted = PreferencesNotifier.create(\n    \"intro_completed\",\n    false,\n    overrideValue: _debugIntroPage && kDebugMode ? false : null,\n  );\n\n  // Null means that auto selection has not been performed yet.\n  static final autoAppsSelectionRegion = PreferencesNotifier.create<Region?, String?>(\n    \"auto_apps_selection_region\",\n    null,\n    mapFrom: (value) => value == null || value.isEmpty ? null : Region.values.byName(value),\n    mapTo: (value) => value == null ? '' : value.name,\n  );\n\n  static final autoAppsSelectionUpdateInterval = PreferencesNotifier.create<double, double>(\n    \"auto_apps_selection_update_interval\",\n    1.0,\n  );\n\n  static final autoAppsSelectionLastUpdate = PreferencesNotifier.create<DateTime?, String?>(\n    \"auto_apps_selection_last_update\",\n    null,\n    mapFrom: (value) => value == null ? null : DateTime.tryParse(value),\n    mapTo: (value) => value?.toIso8601String(),\n  );\n\n  static final includeApps = PreferencesNotifier.create<List<String>, List<String>>(\n    \"per_app_proxy_include_list\",\n    <String>[],\n  );\n\n  static final excludeApps = PreferencesNotifier.create<List<String>, List<String>>(\n    \"per_app_proxy_exclude_list\",\n    <String>[],\n  );\n\n  static final windowMaximized = PreferencesNotifier.create<bool, bool>(\"window_maximized\", false);\n\n  static final windowPosition = PreferencesNotifier.create<Offset?, String?>(\n    \"window_position\",\n    null,\n    mapFrom: (value) {\n      if (value == null) return null;\n      final list = value.split(',').map((e) => double.tryParse(e)).toList();\n      return Offset(list[0]!, list[1]!);\n    },\n    mapTo: (value) {\n      if (value == null) return null;\n      return \"${value.dx},${value.dy}\";\n    },\n  );\n\n  static final windowSize = PreferencesNotifier.create<Size, String>(\n    \"window_size\",\n    defaultWindowSize,\n    mapFrom: (value) {\n      final list = value.split(',').map((e) => double.tryParse(e)).toList();\n      return Size(list[0]!, list[1]!);\n    },\n    mapTo: (value) => \"${value.width},${value.height}\",\n  );\n\n  static final silentStart = PreferencesNotifier.create<bool, bool>(\"silent_start\", false);\n\n  static final disableMemoryLimit = PreferencesNotifier.create<bool, bool>(\n    \"disable_memory_limit\",\n    // disable memory limit on desktop by default\n    PlatformUtils.isDesktop,\n  );\n\n  static final perAppProxyMode = PreferencesNotifier.create<PerAppProxyMode, String>(\n    \"per_app_proxy_mode\",\n    PerAppProxyMode.off,\n    mapFrom: PerAppProxyMode.values.byName,\n    mapTo: (value) => value.name,\n  );\n\n  static final markNewProfileActive = PreferencesNotifier.create<bool, bool>(\"mark_new_profile_active\", true);\n\n  static final dynamicNotification = PreferencesNotifier.create<bool, bool>(\"dynamic_notification\", true);\n\n  static final autoCheckIp = PreferencesNotifier.create<bool, bool>(\"auto_check_ip\", true);\n\n  static final startedByUser = PreferencesNotifier.create<bool, bool>(\"started_by_user\", false);\n\n  static final storeReviewedByUser = PreferencesNotifier.create<bool, bool>(\"store_reviewed_by_user\", false);\n\n  static final actionAtClose = PreferencesNotifier.create<ActionsAtClosing, String>(\n    \"action_at_close\",\n    ActionsAtClosing.ask,\n    mapFrom: ActionsAtClosing.values.byName,\n    mapTo: (value) => value.name,\n  );\n}\n\n@Riverpod(keepAlive: true)\nclass DebugModeNotifier extends _$DebugModeNotifier {\n  late final _pref = PreferencesEntry(\n    preferences: ref.watch(sharedPreferencesProvider).requireValue,\n    key: \"debug_mode\",\n    defaultValue: ref.read(environmentProvider) == Environment.dev,\n  );\n\n  @override\n  bool build() => _pref.read();\n\n  Future<void> update(bool value) {\n    state = value;\n    return _pref.write(value);\n  }\n}\n"
  },
  {
    "path": "lib/core/preferences/preferences_migration.dart",
    "content": "import 'package:hiddify/utils/utils.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\nclass PreferencesMigration with InfraLogger {\n  PreferencesMigration({required this.sharedPreferences});\n\n  final SharedPreferences sharedPreferences;\n\n  static const versionKey = \"preferences_version\";\n\n  Future<void> migrate() async {\n    final currentVersion = sharedPreferences.getInt(versionKey) ?? 0;\n\n    final migrationSteps = [PreferencesVersion1Migration(sharedPreferences)];\n\n    if (currentVersion == migrationSteps.length) {\n      loggy.debug(\"already using the latest version (v$currentVersion)\");\n      return;\n    }\n\n    final stopWatch = Stopwatch()..start();\n    loggy.debug(\"migrating from v[$currentVersion] to v[${migrationSteps.length}]\");\n    for (int i = currentVersion; i < migrationSteps.length; i++) {\n      loggy.debug(\"step [$i](v${i + 1})\");\n      await migrationSteps[i].migrate();\n      await sharedPreferences.setInt(versionKey, i + 1);\n    }\n    stopWatch.stop();\n    loggy.debug(\"migration took [${stopWatch.elapsedMilliseconds}]ms\");\n  }\n}\n\nabstract interface class PreferencesMigrationStep {\n  PreferencesMigrationStep(this.sharedPreferences);\n\n  final SharedPreferences sharedPreferences;\n\n  Future<void> migrate();\n}\n\nclass PreferencesVersion1Migration extends PreferencesMigrationStep with InfraLogger {\n  PreferencesVersion1Migration(super.sharedPreferences);\n\n  @override\n  Future<void> migrate() async {\n    if (sharedPreferences.getString(\"service-mode\") case final String serviceMode) {\n      final newMode = switch (serviceMode) {\n        \"proxy\" || \"system-proxy\" || \"vpn\" => serviceMode,\n        \"systemProxy\" => \"system-proxy\",\n        \"tun\" => \"vpn\",\n        _ => PlatformUtils.isDesktop ? \"system-proxy\" : \"vpn\",\n      };\n      loggy.debug(\"changing service-mode from [$serviceMode] to [$newMode]\");\n      await sharedPreferences.setString(\"service-mode\", newMode);\n    }\n\n    if (sharedPreferences.getString(\"ipv6-mode\") case final String ipv6Mode) {\n      loggy.debug(\"changing ipv6-mode from [$ipv6Mode] to [${_ipv6Mapper(ipv6Mode)}]\");\n      await sharedPreferences.setString(\"ipv6-mode\", _ipv6Mapper(ipv6Mode));\n    }\n\n    if (sharedPreferences.getString(\"remote-domain-dns-strategy\") case final String remoteDomainStrategy) {\n      loggy.debug(\n        \"changing [remote-domain-dns-strategy] = [$remoteDomainStrategy] to [remote-dns-domain-strategy] = [${_domainStrategyMapper(remoteDomainStrategy)}]\",\n      );\n      await sharedPreferences.remove(\"remote-domain-dns-strategy\");\n      await sharedPreferences.setString(\"remote-dns-domain-strategy\", _domainStrategyMapper(remoteDomainStrategy));\n    }\n\n    if (sharedPreferences.getString(\"direct-domain-dns-strategy\") case final String directDomainStrategy) {\n      loggy.debug(\n        \"changing [direct-domain-dns-strategy] = [$directDomainStrategy] to [direct-dns-domain-strategy] = [${_domainStrategyMapper(directDomainStrategy)}]\",\n      );\n      await sharedPreferences.remove(\"direct-domain-dns-strategy\");\n      await sharedPreferences.setString(\"direct-dns-domain-strategy\", _domainStrategyMapper(directDomainStrategy));\n    }\n\n    if (sharedPreferences.getInt(\"localDns-port\") case final int directPort) {\n      loggy.debug(\"changing [localDns-port] to [direct-port]\");\n      await sharedPreferences.remove(\"localDns-port\");\n      await sharedPreferences.setInt(\"direct-port\", directPort);\n    }\n\n    await sharedPreferences.remove(\"execute-config-as-is\");\n    await sharedPreferences.remove(\"enable-tun\");\n    await sharedPreferences.remove(\"set-system-proxy\");\n\n    await sharedPreferences.remove(\"cron_profiles_update\");\n  }\n\n  String _ipv6Mapper(String persisted) => switch (persisted) {\n    \"ipv4_only\" || \"prefer_ipv4\" || \"prefer_ipv4\" || \"ipv6_only\" => persisted,\n    \"disable\" => \"ipv4_only\",\n    \"enable\" => \"prefer_ipv4\",\n    \"prefer\" => \"prefer_ipv6\",\n    \"only\" => \"ipv6_only\",\n    _ => \"ipv4_only\",\n  };\n\n  String _domainStrategyMapper(String persisted) => switch (persisted) {\n    \"ipv4_only\" || \"prefer_ipv4\" || \"prefer_ipv4\" || \"ipv6_only\" => persisted,\n    \"auto\" => \"\",\n    \"preferIpv6\" => \"prefer_ipv6\",\n    \"preferIpv4\" => \"prefer_ipv4\",\n    \"ipv4Only\" => \"ipv4_only\",\n    \"ipv6Only\" => \"ipv6_only\",\n    _ => \"\",\n  };\n}\n"
  },
  {
    "path": "lib/core/preferences/preferences_provider.dart",
    "content": "import 'dart:io';\n\nimport 'package:hiddify/core/model/environment.dart';\nimport 'package:hiddify/utils/platform_utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:loggy/loggy.dart';\nimport 'package:path/path.dart' as p;\nimport 'package:path_provider/path_provider.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\npart 'preferences_provider.g.dart';\n\n@Riverpod(keepAlive: true)\nFuture<SharedPreferences> sharedPreferences(Ref ref) async {\n  final logger = Loggy(\"preferences\");\n  SharedPreferences? sharedPreferences;\n\n  logger.debug(\"initializing preferences\");\n  try {\n    if (PlatformUtils.isWindows && Environment.isPortable) SharedPreferences.setPrefix('portable.');\n    sharedPreferences = await SharedPreferences.getInstance();\n  } catch (e) {\n    logger.error(\"error initializing preferences\", e);\n    if (!Platform.isWindows && !Platform.isLinux) {\n      rethrow;\n    }\n    // https://github.com/flutter/flutter/issues/89211\n    final directory = await getApplicationSupportDirectory();\n    final file = File(p.join(directory.path, 'shared_preferences.json'));\n    if (file.existsSync()) {\n      file.deleteSync();\n    }\n  }\n\n  return sharedPreferences ??= await SharedPreferences.getInstance();\n}\n"
  },
  {
    "path": "lib/core/router/adaptive_layout/my_adaptive_layout.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/router/adaptive_layout/shell_route_action.dart';\nimport 'package:hiddify/core/router/go_router/helper/active_breakpoint_notifier.dart';\nimport 'package:hiddify/core/router/go_router/routing_config_notifier.dart';\nimport 'package:hiddify/features/stats/widget/side_bar_stats_overview.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass MyAdaptiveLayout extends HookConsumerWidget {\n  const MyAdaptiveLayout({\n    super.key,\n    required this.navigationShell,\n    required this.isMobileBreakpoint,\n    required this.showProfilesAction,\n  });\n  // managed by go router(Shell Route)\n  final StatefulNavigationShell navigationShell;\n  final bool isMobileBreakpoint;\n  final bool showProfilesAction;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    // focus switch management\n    final primaryFocusHash = useState<int?>(null);\n    final navScopeNode = useFocusScopeNode();\n    useEffect(() {\n      bool handler(KeyEvent event) {\n        final arrows = isMobileBreakpoint ? KeyboardConst.verticalArrows : KeyboardConst.horizontalArrows;\n        if (!arrows.contains(event.logicalKey)) return false;\n        if (event is KeyDownEvent) {\n          primaryFocusHash.value = FocusManager.instance.primaryFocus.hashCode;\n        } else {\n          // focus node does not change => true.\n          if (primaryFocusHash.value == FocusManager.instance.primaryFocus.hashCode) {\n            if (branchesScope.values.any((node) => node.hasFocus)) {\n              navScopeNode.requestFocus();\n            } else if (navScopeNode.hasFocus) {\n              branchesScope[getNameOfBranch(isMobileBreakpoint, showProfilesAction, navigationShell.currentIndex)]\n                  ?.requestFocus();\n            }\n          }\n        }\n        return true;\n      }\n\n      HardwareKeyboard.instance.addHandler(handler);\n      return () {\n        HardwareKeyboard.instance.removeHandler(handler);\n      };\n    }, [isMobileBreakpoint, showProfilesAction, navigationShell.currentIndex]);\n    return Material(\n      child: Scaffold(\n        body: isMobileBreakpoint\n            ? navigationShell\n            : Row(\n                children: [\n                  FocusScope(\n                    node: navScopeNode,\n                    child: NavigationRail(\n                      extended: Breakpoint(context).isDesktop(),\n                      destinations: _navRailDests(_actions(t, showProfilesAction, isMobileBreakpoint)),\n                      selectedIndex: navigationShell.currentIndex,\n                      onDestinationSelected: (index) => _onTap(context, index),\n                      trailing: Breakpoint(context).isDesktop()\n                          ? const Expanded(\n                              child: Align(\n                                alignment: Alignment.bottomCenter,\n                                child: SizedBox(width: 220, child: SideBarStatsOverview()),\n                              ),\n                            )\n                          : null,\n                    ),\n                  ),\n                  Expanded(child: navigationShell),\n                ],\n              ),\n        bottomNavigationBar: isMobileBreakpoint\n            ? FocusScope(\n                node: navScopeNode,\n                child: NavigationBar(\n                  selectedIndex: navigationShell.currentIndex <= 1 ? navigationShell.currentIndex : 0,\n                  destinations: _navDests(_actions(t, showProfilesAction, isMobileBreakpoint)),\n                  onDestinationSelected: (index) => _onTap(context, index),\n                ),\n              )\n            : null,\n      ),\n    );\n  }\n\n  // shell route action onTap\n  void _onTap(BuildContext context, int index) {\n    navigationShell.goBranch(index, initialLocation: index == navigationShell.currentIndex);\n  }\n\n  List<ShellRouteAction> _actions(Translations t, bool showProfilesAction, bool isMobileBreakpoint) => [\n    ShellRouteAction(Icons.power_settings_new_rounded, t.pages.home.title),\n    if (showProfilesAction && !isMobileBreakpoint) ShellRouteAction(Icons.view_list_rounded, t.pages.profiles.title),\n    ShellRouteAction(Icons.settings_rounded, t.pages.settings.title),\n    if (!isMobileBreakpoint) ShellRouteAction(Icons.description_rounded, t.pages.logs.title),\n    if (!isMobileBreakpoint) ShellRouteAction(Icons.info_rounded, t.pages.about.title),\n  ];\n\n  List<NavigationDestination> _navDests(List<ShellRouteAction> actions) =>\n      actions.map((e) => NavigationDestination(icon: Icon(e.icon), label: e.title)).toList();\n  List<NavigationRailDestination> _navRailDests(List<ShellRouteAction> actions) =>\n      actions.map((e) => NavigationRailDestination(icon: Icon(e.icon), label: Text(e.title))).toList();\n}\n"
  },
  {
    "path": "lib/core/router/adaptive_layout/shell_route_action.dart",
    "content": "import 'package:flutter/material.dart';\n\n//Helper class for storing details for each navigation action in my_adaptive_layout.dart\nclass ShellRouteAction {\n  final IconData icon;\n  final String title;\n\n  ShellRouteAction(this.icon, this.title);\n}\n"
  },
  {
    "path": "lib/core/router/bottom_sheets/bottom_sheets_notifier.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/router/bottom_sheets/widgets/auto_apps_selection_modal.dart';\nimport 'package:hiddify/core/router/bottom_sheets/widgets/quick_settings_modal.dart';\nimport 'package:hiddify/core/router/go_router/go_router_notifier.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_mode.dart';\nimport 'package:hiddify/features/profile/add/add_profile_modal.dart';\nimport 'package:hiddify/features/profile/overview/profiles_modal.dart';\n\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'bottom_sheets_notifier.g.dart';\n\n@riverpod\nclass BottomSheetsNotifier extends _$BottomSheetsNotifier {\n  @override\n  void build() {}\n\n  Future<T?> _show<T>({required Widget child, required bool isScrollControlled}) async {\n    final context = rootNavKey.currentContext;\n    if (context == null) return null;\n    // ref.read(popupCountNotifierProvider.notifier).increase();\n    return await Navigator.of(context)\n        .push<T>(\n          ModalBottomSheetRoute(\n            constraints: BottomSheetConst.boxConstraints,\n            isScrollControlled: isScrollControlled,\n            builder: (context) => ClipRRect(\n              borderRadius: BottomSheetConst.borderRadius,\n              child: Material(\n                child: Padding(\n                  padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),\n                  child: child,\n                ),\n              ),\n            ),\n          ),\n        )\n        .then((value) {\n          // ref.read(popupCountNotifierProvider.notifier).decrease();\n          return value;\n        });\n  }\n\n  Future<void> showAddProfile({String? url}) async =>\n      await _show(isScrollControlled: true, child: AddProfileModal(url: url));\n\n  Future<void> showProfilesOverview() async => await _show(isScrollControlled: true, child: const ProfilesModal());\n\n  Future<void> showQuickSettings() async => await _show(isScrollControlled: false, child: const QuickSettingsModal());\n  Future<void> showAutoAppsSelection({required AppProxyMode mode}) async =>\n      await _show(isScrollControlled: false, child: AutoAppsSelectionModal(mode: mode));\n}\n"
  },
  {
    "path": "lib/core/router/bottom_sheets/widgets/auto_apps_selection_modal.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_mode.dart';\nimport 'package:hiddify/features/per_app_proxy/overview/per_app_proxy_loading_notifier.dart';\nimport 'package:hiddify/features/per_app_proxy/overview/per_app_proxy_notifier.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass AutoAppsSelectionModal extends HookConsumerWidget {\n  const AutoAppsSelectionModal({super.key, required this.mode});\n\n  final AppProxyMode mode;\n\n  String _genSliderText(Translations t, int sliderValue) {\n    final day = t.common.interval.day(n: sliderValue);\n    return day;\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final theme = Theme.of(context);\n    final loading = ref.watch(appProxyLoadingProvider);\n    final isAutoEnabled = ref.watch(Preferences.autoAppsSelectionRegion) != null;\n    final updateInterval = ref.watch(Preferences.autoAppsSelectionUpdateInterval);\n    final sliderFocusNode = useFocusNode(\n      onKeyEvent: (node, event) {\n        if (KeyboardConst.verticalArrows.contains(event.logicalKey) && event is KeyDownEvent) {\n          if (event.logicalKey == LogicalKeyboardKey.arrowUp) {\n            node.previousFocus();\n          } else {\n            node.nextFocus();\n          }\n          return KeyEventResult.handled;\n        }\n        return KeyEventResult.ignored;\n      },\n    );\n    useEffect(() {\n      if (!isAutoEnabled) {\n        WidgetsBinding.instance.addPostFrameCallback((_) async {\n          await ref\n              .read(appProxyLoadingProvider.notifier)\n              .doAsync(ref.read(PerAppProxyProvider(mode).notifier).applyAutoSelection);\n        });\n      }\n      return null;\n    }, []);\n    return SafeArea(\n      child: SingleChildScrollView(\n        child: Column(\n          children: [\n            ListTile(\n              title: Text(t.pages.settings.routing.perAppProxy.autoSelection.title),\n              trailing: AnimatedSwitcher(\n                duration: const Duration(milliseconds: 300),\n                child: loading\n                    ? const Padding(\n                        padding: EdgeInsetsDirectional.only(end: 10),\n                        child: SizedBox(width: 32, height: 32, child: CircularProgressIndicator()),\n                      )\n                    : Switch.adaptive(\n                        value: isAutoEnabled,\n                        onChanged: (value) async {\n                          final notifier = ref.read(appProxyLoadingProvider.notifier);\n                          if (value) {\n                            await notifier.doAsync(ref.read(PerAppProxyProvider(mode).notifier).applyAutoSelection);\n                          } else {\n                            await notifier.doAsync(ref.read(PerAppProxyProvider(mode).notifier).clearAutoSelected);\n                            if (context.mounted) context.pop();\n                          }\n                        },\n                      ),\n              ),\n            ),\n            AnimatedSize(\n              alignment: Alignment.topCenter,\n              duration: const Duration(milliseconds: 300),\n              curve: Curves.easeInOut,\n              child: isAutoEnabled\n                  ? Column(\n                      children: [\n                        const Divider(height: 1),\n                        Padding(\n                          padding: const EdgeInsets.symmetric(horizontal: 16).copyWith(top: 16),\n                          child: Row(\n                            children: [\n                              Expanded(\n                                child: Text(\n                                  t.pages.settings.routing.perAppProxy.autoSelection.autoUpdateInterval,\n                                  style: theme.textTheme.titleSmall!.copyWith(color: theme.colorScheme.onSurface),\n                                ),\n                              ),\n                              Text(\n                                _genSliderText(t, updateInterval.round()),\n                                style: theme.textTheme.labelSmall!.copyWith(color: theme.colorScheme.onSurfaceVariant),\n                              ),\n                            ],\n                          ),\n                        ),\n                        const Gap(4),\n                        Padding(\n                          padding: const EdgeInsets.symmetric(horizontal: 10),\n                          child: Slider(\n                            focusNode: sliderFocusNode,\n                            value: updateInterval,\n                            min: 1,\n                            max: 7,\n                            divisions: 7,\n                            label: updateInterval.round().toString(),\n                            onChanged: (double value) {\n                              ref.read(Preferences.autoAppsSelectionUpdateInterval.notifier).update(value);\n                            },\n                          ),\n                        ),\n                        Padding(\n                          padding: const EdgeInsets.symmetric(horizontal: 16).copyWith(bottom: 8),\n                          child: Row(\n                            children: [\n                              Expanded(\n                                child: FilledButton(\n                                  onPressed: loading\n                                      ? null\n                                      : () async {\n                                          await ref\n                                              .read(appProxyLoadingProvider.notifier)\n                                              .doAsync(ref.read(PerAppProxyProvider(mode).notifier).applyAutoSelection);\n                                        },\n                                  child: Text(t.pages.settings.routing.perAppProxy.autoSelection.performNow),\n                                ),\n                              ),\n                              const Gap(8),\n                              FilledButton.tonal(\n                                onPressed: loading\n                                    ? null\n                                    : () async {\n                                        await ref\n                                            .read(appProxyLoadingProvider.notifier)\n                                            .doAsync(\n                                              ref.read(PerAppProxyProvider(mode).notifier).revertForceDeselection,\n                                            );\n                                      },\n                                child: Text(t.pages.settings.routing.perAppProxy.autoSelection.resetToDefault),\n                              ),\n                            ],\n                          ),\n                        ),\n                      ],\n                    )\n                  : const SizedBox.shrink(),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/bottom_sheets/widgets/quick_settings_modal.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/notifier/warp_option/warp_option_notifier.dart';\nimport 'package:hiddify/singbox/model/singbox_config_enum.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass QuickSettingsModal extends HookConsumerWidget {\n  const QuickSettingsModal({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    return SafeArea(\n      child: SingleChildScrollView(\n        child: Column(\n          children: [\n            Padding(\n              padding: const EdgeInsets.symmetric(horizontal: 16).copyWith(top: 16),\n              child: SegmentedButton(\n                showSelectedIcon: false,\n                segments: ServiceMode.choices\n                    .map(\n                      (e) => ButtonSegment(\n                        value: e,\n                        label: Padding(\n                          padding: const EdgeInsets.symmetric(vertical: 8),\n                          child: Text(e.presentShort(t), textAlign: TextAlign.center),\n                        ),\n                        // tooltip: e.isExperimental ? t.settings.experimental : null,\n                      ),\n                    )\n                    .toList(),\n                selected: {ref.watch(ConfigOptions.serviceMode)},\n                onSelectionChanged: (newSet) => ref.read(ConfigOptions.serviceMode.notifier).update(newSet.first),\n              ),\n            ),\n            const Gap(12),\n            ListTile(\n              leading: const Icon(Icons.cloud_rounded),\n              title: Text(ref.watch(ConfigOptions.warpDetourMode).presentExplain(t)),\n              onLongPress: () {\n                context.pop();\n                context.goNamed('warpOptions');\n              },\n              onTap: () async {\n                final value = ref.watch(ConfigOptions.enableWarp);\n                await ref.read(ConfigOptions.enableWarp.notifier).update(!value);\n              },\n              trailing: Switch.adaptive(\n                value: ref.watch(ConfigOptions.enableWarp),\n                onChanged: (value) async {\n                  await ref.read(ConfigOptions.enableWarp.notifier).update(value);\n                  // await ref.read(warpOptionNotifierProvider.notifier).genWarps();\n                },\n              ),\n            ),\n            // ListTile(\n\n            //   leading: const Icon(Icons.content_cut_rounded),\n            //   title: Text(t.pages.settings.tlsTricks.title),\n            //   onTap: () {\n            //     context.pop();\n            //     context.goNamed('tlsTricks');\n            //   },\n            //   trailing: Switch.adaptive(\n            //     value: ref.watch(ConfigOptions.enableTlsFragment),\n            //     onChanged: ref.read(ConfigOptions.enableTlsFragment.notifier).update,\n            //   ),\n            // ),\n            const Gap(16),\n          ],\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/deep_linking/my_app_links.dart",
    "content": "import 'package:app_links/app_links.dart';\nimport 'package:hiddify/core/router/deep_linking/url_protocol/api.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'my_app_links.g.dart';\n\n@riverpod\nStream<String> myAppLinks(Ref ref) async* {\n  if (PlatformUtils.isWindows) {\n    for (final protocol in LinkParser.protocols) {\n      registerProtocolHandler(protocol);\n    }\n  }\n  yield* AppLinks().uriLinkStream.map((event) => event.toString());\n}\n"
  },
  {
    "path": "lib/core/router/deep_linking/url_protocol/README_url_protocol.md",
    "content": "# Deep Linking for Windows\n## Custom scheme setup for registration\n## the source available in the app_links project was used instead of the win32_registry package.\n\n#### url_protocol folder:\n```\nhttps://github.com/llfbandit/app_links/tree/master/app_links/example/lib/url_protocol\n```\n\n#### doc:\n```\nhttps://github.com/llfbandit/app_links/blob/master/doc/README_windows.md\n```"
  },
  {
    "path": "lib/core/router/deep_linking/url_protocol/api.dart",
    "content": "import 'package:hiddify/core/router/deep_linking/url_protocol/windows_protocol.dart'\n    if (dart.library.js_interop) 'web_url_protocol.dart';\n\n/// Registers a protocol by [scheme] to allow for links in the form `<scheme>://...`\n/// to be processed by this application. By default, opening a link will open\n/// the executable that was used to register the scheme with the URL as the first\n/// argument passed to the executable.\n///\n/// If a protocol is already registered for the given scheme, this function will\n/// attempt to overwrite the previous handler with the current executable information.\n/// However, note that depending on process permissions, this operation may be\n/// disallowed by the underlying platform.\n///\n/// You may pass an [executable] to override the path to the executable to run\n/// when accessing the URL.\n///\n/// [arguments] is a list of arguments to be used when running the executable.\n/// If passed, the list must contain at least one element, and at least one of\n/// those elements must contain the literal value `%s` to denote the URL to open.\n/// Quoting arguments is not necessary, as this will be handled for you.\n/// Escaping the `%s` as an unprocessed literal is currently unsupported.\nvoid registerProtocolHandler(String scheme, {String? executable, List<String>? arguments}) {\n  WindowsProtocolHandler().register(scheme, executable: executable, arguments: arguments);\n}\n\n/// Unregisters the protocol handler with the underlying platform. The provided\n/// [scheme] will no longer be used in links.\n///\n/// Note that this will unregister a protocol by scheme regardless of which process\n/// had registered it. Unregistering a scheme that was not registered by this\n/// application is undefined and depends on platform-specific restrictions.\nvoid unregisterProtocolHandler(String scheme) {\n  WindowsProtocolHandler().unregister(scheme);\n}\n"
  },
  {
    "path": "lib/core/router/deep_linking/url_protocol/protocol.dart",
    "content": "abstract class ProtocolHandler {\n  void register(String scheme, {String? executable, List<String>? arguments});\n\n  void unregister(String scheme);\n\n  List<String> getArguments(List<String>? arguments) {\n    if (arguments == null) return ['%s'];\n\n    if (arguments.isEmpty && !arguments.any((e) => e.contains('%s'))) {\n      throw ArgumentError('arguments must contain at least 1 instance of \"%s\"');\n    }\n\n    return arguments;\n  }\n}\n"
  },
  {
    "path": "lib/core/router/deep_linking/url_protocol/web_url_protocol.dart",
    "content": "import 'package:hiddify/core/router/deep_linking/url_protocol/protocol.dart';\n\nclass WindowsProtocolHandler extends ProtocolHandler {\n  @override\n  void register(String scheme, {String? executable, List<String>? arguments}) {}\n\n  @override\n  void unregister(String scheme) {}\n}\n"
  },
  {
    "path": "lib/core/router/deep_linking/url_protocol/windows_protocol.dart",
    "content": "import 'dart:io';\n\nimport 'package:ffi/ffi.dart';\nimport 'package:flutter/foundation.dart';\nimport 'package:hiddify/core/router/deep_linking/url_protocol/protocol.dart';\nimport 'package:win32/win32.dart';\n\nconst _hive = HKEY_CURRENT_USER;\n\nclass WindowsProtocolHandler extends ProtocolHandler {\n  @override\n  void register(String scheme, {String? executable, List<String>? arguments}) {\n    if (defaultTargetPlatform != TargetPlatform.windows) return;\n\n    final prefix = _regPrefix(scheme);\n    final capitalized = scheme[0].toUpperCase() + scheme.substring(1);\n    final args = getArguments(arguments).map((a) => _sanitize(a));\n    final cmd = '${executable ?? Platform.resolvedExecutable} ${args.join(' ')}';\n\n    _regCreateStringKey(_hive, prefix, '', 'URL:$capitalized');\n    _regCreateStringKey(_hive, prefix, 'URL Protocol', '');\n    _regCreateStringKey(_hive, '$prefix\\\\shell\\\\open\\\\command', '', cmd);\n  }\n\n  @override\n  void unregister(String scheme) {\n    if (defaultTargetPlatform != TargetPlatform.windows) return;\n\n    final txtKey = TEXT(_regPrefix(scheme));\n    try {\n      RegDeleteTree(HKEY_CURRENT_USER, txtKey);\n    } finally {\n      free(txtKey);\n    }\n  }\n\n  String _regPrefix(String scheme) => 'SOFTWARE\\\\Classes\\\\$scheme';\n\n  int _regCreateStringKey(int hKey, String key, String valueName, String data) {\n    final txtKey = TEXT(key);\n    final txtValue = TEXT(valueName);\n    final txtData = TEXT(data);\n    try {\n      return RegSetKeyValue(hKey, txtKey, txtValue, REG_SZ, txtData, txtData.length * 2 + 2);\n    } finally {\n      free(txtKey);\n      free(txtValue);\n      free(txtData);\n    }\n  }\n\n  String _sanitize(String value) {\n    value = value.replaceAll(r'%s', '%1').replaceAll(r'\"', '\\\\\"');\n    return '\"$value\"';\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/dialog_notifier.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/preferences/actions_at_closing.dart';\nimport 'package:hiddify/core/router/dialog/widgets/action_at_closing_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/confirmation_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/custom_alert_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/experimental_feature_notice.dart';\nimport 'package:hiddify/core/router/dialog/widgets/free_profile_consent_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/new_version_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/no_active_profile_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/ok_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/proxy_info_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/save_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/setting_checkbox_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/setting_input_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/setting_picker_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/setting_radio_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/setting_slider_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/setting_text_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/sort_profiles_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/unknown_domains_warning_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/warp_license_dialog.dart';\nimport 'package:hiddify/core/router/dialog/widgets/window_closing_dialog.dart';\nimport 'package:hiddify/core/router/go_router/go_router_notifier.dart';\nimport 'package:hiddify/features/app_update/model/remote_version_entity.dart';\nimport 'package:hiddify/features/common/qr_code_dialog.dart';\nimport 'package:hiddify/features/common/qr_code_scanner_screen.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:protobuf/protobuf.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'dialog_notifier.g.dart';\n\n@Riverpod(keepAlive: true)\nclass DialogNotifier extends _$DialogNotifier {\n  @override\n  void build() {}\n\n  Future<T?> _show<T>(Widget child) async {\n    final context = rootNavKey.currentContext;\n    if (context == null) return null;\n    // ref.read(popupCountNotifierProvider.notifier).increase();\n    return await Navigator.of(context).push<T>(DialogRoute(context: context, builder: (context) => child)).then((\n      value,\n    ) {\n      // ref.read(popupCountNotifierProvider.notifier).decrease();\n      return value;\n    });\n  }\n\n  Future<String?> showQrScanner() async {\n    return await _show<String?>(const QrCodeScannerDialog());\n  }\n\n  Future<void> showSortProfiles() async {\n    return await _show<void>(const SortProfilesDialog());\n  }\n\n  Future<bool> showWarpLicense() async {\n    return await _show<bool?>(const WarpLicenseDialog()) ?? false;\n  }\n\n  Future<void> showQrCode(String link, {String? message}) async {\n    return await _show<void>(QrCodeDialog(link, message: message));\n  }\n\n  Future<void> showOk(String title, String description) async {\n    return await _show<void>(OkDialog(title: title, description: description));\n  }\n\n  Future<double?> showSettingSlider({\n    required String title,\n    required double initialValue,\n    VoidCallback? onReset,\n    double min = 0,\n    double max = 1,\n    int? divisions,\n    String Function(double value)? labelGen,\n  }) async {\n    return await _show<double?>(\n      SettingsSliderDialog(\n        title: title,\n        initialValue: initialValue,\n        onReset: onReset,\n        min: min,\n        max: max,\n        divisions: divisions,\n        labelGen: labelGen,\n      ),\n    );\n  }\n\n  Future<void> showNewVersion({\n    required String currentVersion,\n    required RemoteVersionEntity newVersion,\n    required bool canIgnore,\n  }) async {\n    return await _show<void>(NewVersionDialog(currentVersion, newVersion, canIgnore: canIgnore));\n  }\n\n  Future<bool> showConfirmation({\n    required String title,\n    required String message,\n    IconData? icon,\n    String? positiveBtnTxt,\n  }) async {\n    return await _show<bool>(\n          ConfirmationDialog(title: title, message: message, icon: icon, positiveBtnTxt: positiveBtnTxt),\n        ) ??\n        false;\n  }\n\n  Future<ActionsAtClosing?> showActionAtClosing({required ActionsAtClosing selected}) async {\n    return await _show<ActionsAtClosing?>(ActionsAtClosingDialog(selected: selected));\n  }\n\n  Future<bool> showExperimentalFeatureNotice() async {\n    final hasExperimental = ref.read(ConfigOptions.hasExperimentalFeatures);\n    final canShowNotice = !ref.read(disableExperimentalFeatureNoticeProvider);\n    if (hasExperimental && canShowNotice) {\n      return await _show<bool?>(const ExperimentalFeatureNoticeDialog()) ?? false;\n    }\n    return true;\n  }\n\n  Future<void> showNoActiveProfile() async {\n    return await _show<void>(const NoActiveProfileDialog());\n  }\n\n  Future<bool> showFreeProfileConsent({required String title, required String consent}) async {\n    return await _show<bool?>(FreeProfileConsentDialog(title: title, consent: consent)) ?? false;\n  }\n\n  Future<bool> showUnknownDomainsWarning({required String url}) async {\n    return await _show<bool?>(UnknownDomainsWarningDialog(url: url)) ?? false;\n  }\n\n  Future<void> showProxyInfo({required OutboundInfo outboundInfo}) async {\n    return await _show<void>(ProxyInfoDialog(outboundInfo: outboundInfo));\n  }\n\n  Future<String?> showSettingText({\n    required String lable,\n    String value = '',\n    String? defaultValue,\n    FormFieldValidator<String>? validator,\n  }) async {\n    return await _show<String?>(\n      SettingTextDialog(lable: lable, value: value, defaultValue: defaultValue, validator: validator),\n    );\n  }\n\n  Future<List<ProtobufEnum>?> showSettingCheckbox({\n    required String title,\n    required List<ProtobufEnum> values,\n    required List<ProtobufEnum> selectedValues,\n    List<ProtobufEnum>? defaultValue,\n    Map<String, String>? t,\n  }) async {\n    return await _show<List<ProtobufEnum>?>(\n      SettingCheckboxDialog(\n        title: title,\n        values: values,\n        selectedValues: selectedValues,\n        defaultValue: defaultValue,\n        t: t,\n      ),\n    );\n  }\n\n  Future<T?> showSettingRadio<T>({\n    required String title,\n    required List<T> values,\n    required T value,\n    T? defaultValue,\n    Map<String, String>? t,\n  }) async {\n    return await _show<T?>(\n      SettingRadioDialog(title: title, values: values, value: value, defaultValue: defaultValue, t: t),\n    );\n  }\n\n  Future<T?> showSettingInput<T>({\n    required String title,\n    required T initialValue,\n    T? Function(String value)? mapTo,\n    bool Function(String value)? validator,\n    String Function(T value)? valueFormatter,\n    List<T>? possibleValues,\n    VoidCallback? onReset,\n    (String text, VoidCallback)? optionalAction,\n    IconData? icon,\n    bool digitsOnly = false,\n  }) async {\n    return await _show<T?>(\n      SettingInputDialog(\n        title: title,\n        initialValue: initialValue,\n        mapTo: mapTo,\n        validator: validator,\n        valueFormatter: valueFormatter,\n        possibleValues: possibleValues,\n        onReset: onReset,\n        optionalAction: optionalAction,\n        icon: icon,\n        digitsOnly: digitsOnly,\n      ),\n    );\n  }\n\n  Future<T?> showSettingPicker<T>({\n    required String title,\n    bool showFlag = false,\n    required T selected,\n    required List<T> options,\n    required String Function(T e) getTitle,\n    VoidCallback? onReset,\n  }) async {\n    return await _show<T?>(\n      SettingPickerDialog(\n        title: title,\n        showFlag: showFlag,\n        selected: selected,\n        options: options,\n        getTitle: getTitle,\n        onReset: onReset,\n      ),\n    );\n  }\n\n  Future<bool?> showSave({required String title, required String description}) async {\n    return await _show<bool?>(SaveDialog(title: title, description: description));\n  }\n\n  Future<void> showWindowClosing() async {\n    return await _show<void>(const WindowClosingDialog());\n  }\n\n  Future<void> showCustomAlert({String? title, required String message}) async {\n    return await _show<void>(CustomAlertDialog(title: title, message: message));\n  }\n\n  Future<void> showCustomAlertFromErr(({String type, String? message}) err) async {\n    return await _show<void>(CustomAlertDialog.fromErr(err));\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/action_at_closing_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/preferences/actions_at_closing.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ActionsAtClosingDialog extends HookConsumerWidget {\n  const ActionsAtClosingDialog({super.key, required this.selected});\n  final ActionsAtClosing selected;\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return SimpleDialog(\n      title: Text(t.pages.settings.general.actionAtClosing),\n      children: ActionsAtClosing.values\n          .map((e) => RadioListTile(title: Text(e.present(t)), value: e, groupValue: selected, onChanged: context.pop))\n          .toList(),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/confirmation_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ConfirmationDialog extends HookConsumerWidget {\n  const ConfirmationDialog({super.key, required this.title, required this.message, this.icon, this.positiveBtnTxt});\n  final String title;\n  final String message;\n  final IconData? icon;\n  final String? positiveBtnTxt;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return AlertDialog(\n      icon: icon != null ? Icon(icon) : null,\n      title: Text(title),\n      content: ConstrainedBox(constraints: AlertDialogConst.boxConstraints, child: Text(message)),\n      actions: [\n        TextButton(onPressed: () => context.pop(false), child: Text(t.common.cancel)),\n        TextButton(onPressed: () => context.pop(true), child: Text(positiveBtnTxt ?? t.common.ok)),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/custom_alert_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass CustomAlertDialog extends HookConsumerWidget {\n  const CustomAlertDialog({super.key, this.title, required this.message});\n\n  final String? title;\n  final String message;\n\n  factory CustomAlertDialog.fromErr(({String type, String? message}) err) =>\n      CustomAlertDialog(title: err.message == null ? null : err.type, message: err.message ?? err.type);\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return AlertDialog(\n      title: title != null ? Text(title!) : null,\n      content: SingleChildScrollView(\n        child: SizedBox(width: 468, child: Text(message, textDirection: TextDirection.ltr)),\n      ),\n      actions: [\n        TextButton(\n          onPressed: () {\n            context.pop();\n          },\n          child: Text(t.common.ok),\n        ),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/experimental_feature_notice.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/foundation.dart';\nimport 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/utils/preferences_utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nbool _testExperimentalNotice = false;\n\nfinal disableExperimentalFeatureNoticeProvider = PreferencesNotifier.createAutoDispose(\n  \"disable_experimental_feature_notice\",\n  false,\n  overrideValue: _testExperimentalNotice && kDebugMode ? false : null,\n);\n\nclass ExperimentalFeatureNoticeDialog extends HookConsumerWidget {\n  const ExperimentalFeatureNoticeDialog({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final disableNotice = ref.watch(disableExperimentalFeatureNoticeProvider);\n\n    return AlertDialog(\n      title: Text(t.dialogs.experimentalNotice.title),\n      content: SingleChildScrollView(\n        child: SizedBox(\n          width: 468,\n          child: Column(\n            mainAxisSize: MainAxisSize.min,\n            crossAxisAlignment: CrossAxisAlignment.start,\n            children: [\n              Text(t.dialogs.experimentalNotice.msg),\n              const Gap(8),\n              CheckboxListTile(\n                value: disableNotice,\n                title: Text(t.dialogs.experimentalNotice.disable),\n                secondary: const Icon(FluentIcons.eye_off_24_regular),\n                onChanged: (value) async =>\n                    await ref.read(disableExperimentalFeatureNoticeProvider.notifier).update(value ?? false),\n                dense: true,\n              ),\n              ListTile(\n                title: Text(t.pages.settings.title),\n                leading: const Icon(FluentIcons.box_edit_24_regular),\n                trailing: const Icon(FluentIcons.chevron_right_20_regular),\n                onTap: () {\n                  context.pop(false);\n                  context.goNamed('settings');\n                },\n                dense: true,\n              ),\n            ],\n          ),\n        ),\n      ),\n      actions: [\n        TextButton(\n          onPressed: () => context.pop(false),\n          child: Text(MaterialLocalizations.of(context).cancelButtonLabel.toUpperCase()),\n        ),\n        TextButton(onPressed: () => context.pop(true), child: Text(t.connection.connect)),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/free_profile_consent_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter_markdown_plus/flutter_markdown_plus.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass FreeProfileConsentDialog extends HookConsumerWidget {\n  const FreeProfileConsentDialog({super.key, required this.title, required this.consent});\n  final String title;\n  final String consent;\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return AlertDialog(\n      title: Text(title),\n      content: ConstrainedBox(\n        constraints: AlertDialogConst.boxConstraints,\n        child: MarkdownBody(\n          data: consent,\n          // styleSheet: MarkdownStyleSheet(textAlign: WrapAlignment.spaceBetween),\n          onTapLink: (text, href, title) => UriUtils.tryLaunch(Uri.parse(href!)),\n        ),\n      ),\n      actions: [\n        TextButton(child: Text(t.common.cancel), onPressed: () => context.pop(false)),\n        TextButton(child: Text(t.common.kContinue), onPressed: () => context.pop(true)),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/new_version_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/features/app_update/model/remote_version_entity.dart';\nimport 'package:hiddify/features/app_update/notifier/app_update_notifier.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass NewVersionDialog extends HookConsumerWidget with PresLogger {\n  NewVersionDialog(this.currentVersion, this.newVersion, {super.key, this.canIgnore = true});\n\n  final String currentVersion;\n  final RemoteVersionEntity newVersion;\n  final bool canIgnore;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final theme = Theme.of(context);\n\n    return AlertDialog(\n      title: Text(t.dialogs.newVersion.title),\n      content: Column(\n        mainAxisSize: MainAxisSize.min,\n        crossAxisAlignment: CrossAxisAlignment.start,\n        children: [\n          Text(t.dialogs.newVersion.msg),\n          const Gap(8),\n          Text.rich(\n            TextSpan(\n              children: [\n                TextSpan(text: t.dialogs.newVersion.currentVersion, style: theme.textTheme.bodySmall),\n                TextSpan(text: currentVersion, style: theme.textTheme.labelMedium),\n              ],\n            ),\n          ),\n          Text.rich(\n            TextSpan(\n              children: [\n                TextSpan(text: t.dialogs.newVersion.newVersion, style: theme.textTheme.bodySmall),\n                TextSpan(text: newVersion.presentVersion, style: theme.textTheme.labelMedium),\n              ],\n            ),\n          ),\n        ],\n      ),\n      actions: [\n        if (canIgnore)\n          TextButton(\n            onPressed: () async {\n              await ref.read(appUpdateNotifierProvider.notifier).ignoreRelease(newVersion);\n              if (context.mounted) context.pop();\n            },\n            child: Text(t.common.ignore),\n          ),\n        TextButton(onPressed: context.pop, child: Text(t.common.later)),\n        TextButton(\n          onPressed: () async {\n            await UriUtils.tryLaunch(Uri.parse(newVersion.url));\n          },\n          child: Text(t.dialogs.newVersion.updateNow),\n        ),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/no_active_profile_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass NoActiveProfileDialog extends HookConsumerWidget {\n  const NoActiveProfileDialog({super.key});\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return AlertDialog(\n      title: Text(t.dialogs.noActiveProfile.title),\n      content: Text(t.dialogs.noActiveProfile.msg),\n      actions: [\n        TextButton(\n          onPressed: () async {\n            await UriUtils.tryLaunch(Uri.parse(t.dialogs.noActiveProfile.helpBtn.url));\n          },\n          child: Text(t.dialogs.noActiveProfile.helpBtn.label),\n        ),\n        TextButton(onPressed: () => context.pop(), child: Text(t.common.ok)),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/ok_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass OkDialog extends HookConsumerWidget {\n  const OkDialog({super.key, required this.title, required this.description});\n  final String title;\n  final String description;\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return AlertDialog(\n      title: Text(title),\n      content: Text(description),\n      actions: [TextButton(child: Text(t.common.ok), onPressed: () => context.pop())],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/proxy_info_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/utils/platform_utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:intl/intl.dart';\nimport 'package:url_launcher/url_launcher.dart';\n\nclass ProxyInfoDialog extends HookConsumerWidget {\n  const ProxyInfoDialog({super.key, required this.outboundInfo});\n\n  final OutboundInfo outboundInfo;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return AlertDialog(\n      title: SelectionArea(child: Text(outboundInfo.tagDisplay)),\n      content: OutboundInfoWidget(outboundInfo: outboundInfo),\n      actions: [TextButton(onPressed: context.pop, child: Text(t.common.close))],\n    );\n  }\n}\n\nclass OutboundInfoWidget extends HookConsumerWidget {\n  final OutboundInfo outboundInfo;\n\n  const OutboundInfoWidget({super.key, required this.outboundInfo});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    // final subOutboundInfo = outboundInfo.groupSelectedTag ?? outboundInfo;\n    return SingleChildScrollView(\n      child: Column(\n        crossAxisAlignment: CrossAxisAlignment.start,\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          // SizedBox(height: 16.0),\n          _buildInfoRow(t.dialogs.proxyInfo.fullTag, outboundInfo.tag),\n          _buildInfoRow(t.dialogs.proxyInfo.type, outboundInfo.type),\n          _buildInfoRow(\n            t.dialogs.proxyInfo.testTime,\n            DateFormat('yyyy-MM-dd HH:mm:ss').format(outboundInfo.urlTestTime.toDateTime().toLocal()),\n          ),\n          _buildInfoRow(t.dialogs.proxyInfo.testDelay, '${outboundInfo.urlTestDelay} ms'),\n          _buildIpInfo(outboundInfo.ipinfo, ref),\n          _buildInfoRow(t.dialogs.proxyInfo.upload, formatBytes(outboundInfo.upload.toInt())),\n          _buildInfoRow(t.dialogs.proxyInfo.download, formatBytes(outboundInfo.download.toInt())),\n          _buildInfoRow(t.dialogs.proxyInfo.isSelected, outboundInfo.isSelected ? '✅' : '❌'),\n          _buildInfoRow(t.dialogs.proxyInfo.isGroup, outboundInfo.isGroup ? '✅' : '❌'),\n          _buildInfoRow(t.dialogs.proxyInfo.isSecure, outboundInfo.isSecure ? '✅' : '❌'),\n          // _buildInfoRow('Is Visible:', outboundInfo.isVisible ? '✅' : '❌'),\n          _buildInfoRow(t.dialogs.proxyInfo.port, outboundInfo.port.toString()),\n          _buildInfoRow(t.dialogs.proxyInfo.host, outboundInfo.host),\n        ],\n      ),\n    );\n  }\n\n  String formatBytes(int bytes, {int decimals = 3}) {\n    if (bytes <= 0) return '0 B';\n\n    const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n    int unitIndex = 0;\n    double size = bytes.toDouble();\n\n    while (size >= 1024 && unitIndex < units.length - 1) {\n      size /= 1024;\n      unitIndex++;\n    }\n    final decimals2 = switch (unitIndex) {\n      0 => 0,\n      1 => 0,\n      2 => 1,\n      _ => decimals,\n    };\n\n    return '${size.toStringAsFixed(decimals2)} ${units[unitIndex]}';\n  }\n\n  Widget _buildInfoRow(String title, String value, {Future<bool>? Function()? onTap}) {\n    if (value.isEmpty || value == '0' || value == '0.0, 0.0') {\n      return const SizedBox();\n    }\n    return Padding(\n      padding: const EdgeInsets.symmetric(vertical: 4.0),\n      child: Row(\n        mainAxisAlignment: MainAxisAlignment.spaceBetween,\n        children: [\n          Text(title, style: const TextStyle(fontWeight: FontWeight.bold)),\n          const SizedBox(width: 8.0),\n          Flexible(\n            child: onTap != null\n                ? GestureDetector(\n                    onTap: onTap,\n                    child: SelectableText(\n                      value,\n                      textAlign: TextAlign.right,\n                      style: const TextStyle(decoration: TextDecoration.underline),\n                    ),\n                  )\n                : SelectableText(value, textAlign: TextAlign.right),\n          ),\n        ],\n      ),\n    );\n  }\n\n  Widget _buildIpInfo(IpInfo ipInfo, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return Column(\n      crossAxisAlignment: CrossAxisAlignment.start,\n      children: [\n        // Text('IP Info:', style: TextStyle(fontWeight: FontWeight.bold)),\n        _buildInfoRow(t.dialogs.proxyInfo.ip, ipInfo.ip),\n        _buildInfoRow(t.dialogs.proxyInfo.countryCode, ipInfo.countryCode),\n        _buildInfoRow(t.dialogs.proxyInfo.region, ipInfo.region), // Handle optional fields\n        _buildInfoRow(t.dialogs.proxyInfo.city, ipInfo.city),\n        _buildInfoRow(t.dialogs.proxyInfo.asn, ipInfo.asn.toString()),\n        _buildInfoRow(t.dialogs.proxyInfo.organization, ipInfo.org),\n        // _buildInfoRow(t.outboundInfo.latitude, ipInfo.latitude.toString()),\n        // _buildInfoRow(t.outboundInfo.longitude, ipInfo.longitude.toString()),\n        _buildInfoRow(\n          t.dialogs.proxyInfo.location,\n          \"${ipInfo.latitude}, ${ipInfo.longitude}\",\n          onTap: () => launchUrl(\n            Uri.parse(\n              !PlatformUtils.isInAppStore\n                  ? 'https://maps.apple.com/?ll=${ipInfo.latitude},${ipInfo.longitude}'\n                  : 'https://www.google.com/maps/@${ipInfo.latitude},${ipInfo.longitude},18z',\n            ),\n          ),\n        ),\n        _buildInfoRow(t.dialogs.proxyInfo.postalCode, ipInfo.postalCode),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/save_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass SaveDialog extends HookConsumerWidget {\n  const SaveDialog({super.key, required this.title, required this.description});\n  final String title;\n  final String description;\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return AlertDialog(\n      title: Text(title),\n      content: ConstrainedBox(constraints: AlertDialogConst.boxConstraints, child: Text(description)),\n      actions: [\n        TextButton(onPressed: () => context.pop(false), child: Text(t.common.discard)),\n        TextButton(onPressed: () => context.pop(true), child: Text(t.common.save)),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/setting_checkbox_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/features/route_rules/notifier/rule_notifier.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:protobuf/protobuf.dart';\n\nclass SettingCheckboxDialog extends ConsumerWidget {\n  const SettingCheckboxDialog({\n    super.key,\n    required this.title,\n    required this.values,\n    required this.selectedValues,\n    this.defaultValue,\n    this.t,\n  });\n\n  final String title;\n  final List<ProtobufEnum> values;\n  final List<ProtobufEnum> selectedValues;\n  final List<ProtobufEnum>? defaultValue;\n  final Map<String, String>? t;\n\n  String textWithTranslation(ProtobufEnum e) {\n    if (t == null) return '$e';\n    return t!['$e'] ?? '$e';\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final checkboxNotififier = dialogCheckboxNotifierProvider(selectedValues);\n    final current = ref.watch(checkboxNotififier);\n\n    return AlertDialog(\n      title: Text(title),\n      content: ConstrainedBox(\n        constraints: const BoxConstraints(maxHeight: 300),\n        child: SingleChildScrollView(\n          child: Column(\n            mainAxisSize: MainAxisSize.min,\n            children: values\n                .map(\n                  (e) => CheckboxListTile(\n                    title: Text(textWithTranslation(e)),\n                    value: current.contains(e),\n                    onChanged: (_) => ref.read(checkboxNotififier.notifier).update(e),\n                  ),\n                )\n                .toList(),\n          ),\n        ),\n      ),\n      actions: [\n        if (defaultValue != null) TextButton(child: Text(t.common.reset), onPressed: () => context.pop(defaultValue)),\n        TextButton(child: Text(t.common.cancel), onPressed: () => context.pop()),\n        TextButton(child: Text(t.common.done), onPressed: () => context.pop(current)),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/setting_input_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:flutter_typeahead/flutter_typeahead.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass SettingInputDialog<T> extends HookConsumerWidget with PresLogger {\n  const SettingInputDialog({\n    super.key,\n    required this.title,\n    required this.initialValue,\n    this.mapTo,\n    this.validator,\n    this.valueFormatter,\n    this.possibleValues,\n    this.onReset,\n    this.optionalAction,\n    this.icon,\n    this.digitsOnly = false,\n  });\n\n  final String title;\n  final T initialValue;\n  final T? Function(String value)? mapTo;\n  final bool Function(String value)? validator;\n  final String Function(T value)? valueFormatter;\n  final List<T>? possibleValues;\n  final VoidCallback? onReset;\n  final (String text, VoidCallback)? optionalAction;\n  final IconData? icon;\n  final bool digitsOnly;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final localizations = MaterialLocalizations.of(context);\n\n    final textController = useTextEditingController(\n      text: valueFormatter?.call(initialValue) ?? initialValue.toString(),\n    );\n    // focus management\n    final okBtnFocusNode = useFocusNode();\n    KeyEventResult handleKeyEvent(FocusNode node, KeyEvent event) {\n      if (KeyboardConst.select.contains(event.logicalKey) && event is KeyDownEvent) {\n        okBtnFocusNode.requestFocus();\n        return KeyEventResult.handled;\n      }\n      return KeyEventResult.ignored;\n    }\n\n    return AlertDialog(\n      title: Text(title),\n      icon: icon != null ? Icon(icon) : null,\n      // material: (context, platform) => MaterialAlertDialogData(\n      //   icon: icon != null ? Icon(icon) : null,\n      // ),\n      content: Column(\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          if (possibleValues != null)\n            // AutocompleteField(initialValue: initialValue.toString(), options: possibleValues!.map((e) => e.toString()).toList())\n            TypeAheadField<String>(\n              controller: textController,\n              builder: (context, controller, focusNode) {\n                focusNode.onKeyEvent = handleKeyEvent;\n                return TextField(\n                  controller: controller,\n                  focusNode: focusNode,\n                  textDirection: TextDirection.ltr,\n                  autofocus: true,\n                  // decoration: InputDecoration(\n                  //     // border: OutlineInputBorder(),\n                  //     // labelText: 'City',\n                  //     )\n                );\n              },\n              // Callback to fetch suggestions based on user input\n              suggestionsCallback: (pattern) {\n                final items = possibleValues!.map((p) => p.toString());\n                var res = items\n                    .where((suggestion) => suggestion.toLowerCase().contains(pattern.toLowerCase()))\n                    .toList();\n                if (res.length <= 1) res = [pattern, ...items.where((s) => s != pattern)];\n                return res;\n              },\n              // Widget to build each suggestion in the list\n              itemBuilder: (context, suggestion) {\n                return ListTile(\n                  contentPadding: const EdgeInsets.symmetric(vertical: 3, horizontal: 10), // Minimize ListTile padding\n                  minTileHeight: 0,\n                  title: Text(\n                    suggestion,\n                    textDirection: TextDirection.ltr,\n                    style: Theme.of(context).textTheme.bodySmall,\n                  ),\n                );\n              },\n              // Callback when a suggestion is selected\n              onSelected: (suggestion) {\n                // Handle the selected suggestion\n                // print('Selected: $suggestion');\n                textController.text = suggestion;\n              },\n            )\n          else\n            CustomTextFormField(\n              controller: textController,\n              inputFormatters: [\n                FilteringTextInputFormatter.singleLineFormatter,\n                if (digitsOnly) FilteringTextInputFormatter.digitsOnly,\n              ],\n              autoCorrect: true,\n              hint: title,\n            ),\n        ],\n      ),\n      actions: [\n        if (optionalAction != null)\n          TextButton(\n            onPressed: () {\n              optionalAction!.$2();\n              context.pop(T == String ? textController.value.text : null);\n            },\n            child: Text(optionalAction!.$1.toUpperCase()),\n          ),\n        if (onReset != null)\n          TextButton(\n            onPressed: () {\n              onReset!();\n              context.pop();\n            },\n            child: Text(t.common.reset),\n          ),\n        TextButton(\n          onPressed: () {\n            context.pop();\n          },\n          child: Text(localizations.cancelButtonLabel.toUpperCase()),\n        ),\n        TextButton(\n          focusNode: okBtnFocusNode,\n          onPressed: () {\n            if (validator?.call(textController.value.text) == false) {\n              context.pop();\n            } else if (mapTo != null) {\n              context.pop(mapTo!.call(textController.value.text));\n            } else {\n              context.pop(T == String ? textController.value.text : null);\n            }\n          },\n          child: Text(localizations.okButtonLabel.toUpperCase()),\n        ),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/setting_picker_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/features/proxy/active/ip_widget.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass SettingPickerDialog<T> extends HookConsumerWidget with PresLogger {\n  const SettingPickerDialog({\n    super.key,\n    required this.title,\n    this.showFlag = false,\n    required this.selected,\n    required this.options,\n    required this.getTitle,\n    this.onReset,\n  });\n\n  final String title;\n  final bool showFlag;\n  final T selected;\n  final List<T> options;\n  final String Function(T e) getTitle;\n  final VoidCallback? onReset;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    return AlertDialog(\n      title: Text(title),\n      content: SingleChildScrollView(\n        child: Column(\n          mainAxisSize: MainAxisSize.min,\n          children: options.map((e) {\n            final title = getTitle(e);\n            final countryCode = title.substring(title.length - 3, title.length - 1);\n            return RadioListTile(\n              title: Text(title),\n              secondary: showFlag ? IPCountryFlag(countryCode: countryCode, size: 32) : null,\n              value: e,\n              groupValue: selected,\n              onChanged: (value) => context.pop(e),\n            );\n          }).toList(),\n        ),\n      ),\n      actions: [\n        if (onReset != null)\n          TextButton(\n            onPressed: () {\n              onReset!();\n              context.pop();\n            },\n            child: Text(t.common.reset),\n          ),\n        TextButton(onPressed: () => context.pop(), child: Text(t.common.cancel)),\n      ],\n      // scrollable: true,\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/setting_radio_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass SettingRadioDialog<T> extends ConsumerWidget {\n  const SettingRadioDialog({\n    super.key,\n    required this.title,\n    required this.values,\n    required this.value,\n    this.defaultValue,\n    this.t,\n  });\n\n  final String title;\n  final List<T> values;\n  final T value;\n  final T? defaultValue;\n  final Map<String, String>? t;\n\n  String textWithTranslation(T e) {\n    if (t == null) return '$e';\n    return t!['$e'] ?? '$e';\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return AlertDialog(\n      title: Text(title),\n      content: ConstrainedBox(\n        constraints: AlertDialogConst.boxConstraints,\n        child: SingleChildScrollView(\n          child: Column(\n            mainAxisSize: MainAxisSize.min,\n            children: values\n                .map(\n                  (e) => RadioListTile<T>(\n                    title: Text(textWithTranslation(e)),\n                    value: e,\n                    groupValue: value,\n                    onChanged: (_) => context.pop(e),\n                  ),\n                )\n                .toList(),\n          ),\n        ),\n      ),\n      actions: [\n        if (defaultValue != null) TextButton(child: Text(t.common.reset), onPressed: () => context.pop(defaultValue)),\n        TextButton(child: Text(t.common.cancel), onPressed: () => context.pop()),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/setting_slider_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass SettingsSliderDialog extends HookConsumerWidget with PresLogger {\n  const SettingsSliderDialog({\n    super.key,\n    required this.title,\n    required this.initialValue,\n    this.onReset,\n    this.min = 0,\n    this.max = 1,\n    this.divisions,\n    this.labelGen,\n  });\n\n  final String title;\n  final double initialValue;\n  final VoidCallback? onReset;\n  final double min;\n  final double max;\n  final int? divisions;\n  final String Function(double value)? labelGen;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final localizations = MaterialLocalizations.of(context);\n\n    final sliderValue = useState(initialValue);\n    final sliderFocusNode = useFocusNode(\n      onKeyEvent: (node, event) {\n        if (KeyboardConst.verticalArrows.contains(event.logicalKey) && event is KeyDownEvent) {\n          if (event.logicalKey == LogicalKeyboardKey.arrowDown) {\n            node.nextFocus();\n          }\n          return KeyEventResult.handled;\n        }\n        return KeyEventResult.ignored;\n      },\n    );\n\n    return AlertDialog(\n      title: Text(title),\n      content: IntrinsicHeight(\n        child: Slider(\n          focusNode: sliderFocusNode,\n          value: sliderValue.value,\n          min: min,\n          max: max,\n          divisions: divisions,\n          onChanged: (value) => sliderValue.value = value,\n          label: labelGen?.call(sliderValue.value),\n        ),\n      ),\n      actions: [\n        if (onReset != null)\n          TextButton(\n            onPressed: () {\n              onReset!();\n              context.pop();\n            },\n            child: Text(t.common.reset),\n          ),\n        TextButton(onPressed: () => context.pop(), child: Text(localizations.cancelButtonLabel.toUpperCase())),\n        TextButton(\n          onPressed: () => context.pop(sliderValue.value),\n          child: Text(localizations.okButtonLabel.toUpperCase()),\n        ),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/setting_text_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass SettingTextDialog extends HookConsumerWidget {\n  const SettingTextDialog({super.key, required this.lable, this.value = '', this.defaultValue, this.validator});\n\n  final String lable;\n  final String value;\n  final String? defaultValue;\n  final FormFieldValidator<String>? validator;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final formKey = useMemoized(() => GlobalKey<FormState>());\n    final tController = useTextEditingController(text: value);\n    return AlertDialog(\n      content: ConstrainedBox(\n        constraints: AlertDialogConst.boxConstraints,\n        child: Form(\n          key: formKey,\n          child: TextFormField(\n            decoration: InputDecoration(label: Text(lable)),\n            controller: tController,\n            validator: (value) {\n              if (value == null || value.isEmpty) return t.pages.settings.routing.routeRule.rule.canNotBeEmpty;\n              if (validator == null) return null;\n              return validator!.call(value);\n            },\n            autofocus: true,\n          ),\n        ),\n      ),\n      actions: [\n        if (defaultValue != null) TextButton(child: Text(t.common.reset), onPressed: () => context.pop(defaultValue)),\n        TextButton(child: Text(t.common.cancel), onPressed: () => context.pop()),\n        TextButton(\n          child: Text(t.common.ok),\n          onPressed: () {\n            if (formKey.currentState!.validate()) {\n              context.pop(tController.text.trim());\n            }\n          },\n        ),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/sort_profiles_dialog.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/features/profile/model/profile_sort_enum.dart';\nimport 'package:hiddify/features/profile/overview/profiles_notifier.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass SortProfilesDialog extends HookConsumerWidget {\n  const SortProfilesDialog({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final sort = ref.watch(profilesSortNotifierProvider);\n\n    return AlertDialog(\n      title: Text(t.dialogs.sortProfiles.title),\n      content: ConstrainedBox(\n        constraints: AlertDialogConst.boxConstraints,\n        child: SingleChildScrollView(\n          child: Column(\n            children: [\n              ...ProfilesSort.values.map((e) {\n                final selected = sort.by == e;\n                final double arrowTurn = sort.mode == SortMode.ascending ? 0 : 0.5;\n\n                return ListTile(\n                  title: Text(e.present(t)),\n                  onTap: () {\n                    if (selected) {\n                      ref.read(profilesSortNotifierProvider.notifier).toggleMode();\n                    } else {\n                      ref.read(profilesSortNotifierProvider.notifier).changeSort(e);\n                    }\n                  },\n                  selected: selected,\n                  leading: Icon(e.icon),\n                  trailing: selected\n                      ? IconButton(\n                          onPressed: () {\n                            ref.read(profilesSortNotifierProvider.notifier).toggleMode();\n                          },\n                          icon: AnimatedRotation(\n                            turns: arrowTurn,\n                            duration: const Duration(milliseconds: 100),\n                            child: Icon(FluentIcons.arrow_sort_up_24_regular, semanticLabel: sort.mode.name),\n                          ),\n                        )\n                      : null,\n                );\n              }),\n            ],\n          ),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/unknown_domains_warning_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass UnknownDomainsWarningDialog extends HookConsumerWidget {\n  const UnknownDomainsWarningDialog({super.key, required this.url});\n\n  final String url;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return AlertDialog(\n      title: Row(\n        children: [\n          const Icon(Icons.warning_rounded, color: Colors.orange),\n          const Gap(8),\n          Text(t.dialogs.unknownDomainsWarning.title),\n        ],\n      ),\n      content: Column(\n        mainAxisSize: MainAxisSize.min,\n        crossAxisAlignment: CrossAxisAlignment.start,\n        children: [\n          Text(t.dialogs.unknownDomainsWarning.youAreAboutToVisit),\n          const Gap(8),\n          Text(url, style: const TextStyle(fontWeight: FontWeight.bold)),\n          const Gap(16),\n          Text(t.dialogs.unknownDomainsWarning.thisWebsiteIsNotInOurTrustedList),\n        ],\n      ),\n      actions: [\n        TextButton(onPressed: () => context.pop(false), child: Text(t.common.cancel)),\n        FilledButton(onPressed: () => context.pop(true), child: Text(t.common.kContinue)),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/warp_license_dialog.dart",
    "content": "import 'package:flutter/gestures.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/utils/uri_utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass WarpLicenseDialog extends HookConsumerWidget {\n  const WarpLicenseDialog({super.key});\n\n  // for focus management\n  KeyEventResult _handleKeyEvent(KeyEvent event, String key) {\n    if (KeyboardConst.select.contains(event.logicalKey) && event is KeyUpEvent) {\n      UriUtils.tryLaunch(Uri.parse(WarpConst.url[key]!));\n      return KeyEventResult.handled;\n    }\n    return KeyEventResult.ignored;\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    // for focus management\n    final focusStates = <String, ValueNotifier<bool>>{\n      WarpConst.warpTermsOfServiceKey: useState<bool>(false),\n      WarpConst.warpPrivacyPolicyKey: useState<bool>(false),\n    };\n    final focusNodes = <String, FocusNode>{\n      WarpConst.warpTermsOfServiceKey: useFocusNode(),\n      WarpConst.warpPrivacyPolicyKey: useFocusNode(),\n    };\n    useEffect(() {\n      for (final entry in focusNodes.entries) {\n        entry.value.addListener(() => focusStates[entry.key]!.value = entry.value.hasPrimaryFocus);\n      }\n      return null;\n    }, []);\n    return AlertDialog(\n      title: Text(t.dialogs.warpLicense.title),\n      content: ConstrainedBox(\n        constraints: AlertDialogConst.boxConstraints,\n        child: SingleChildScrollView(\n          child: Column(\n            children: [\n              Focus(\n                focusNode: focusNodes[WarpConst.warpTermsOfServiceKey],\n                onKeyEvent: (node, event) => _handleKeyEvent(event, WarpConst.warpTermsOfServiceKey),\n                child: const Gap(0.1),\n              ),\n              Focus(\n                focusNode: focusNodes[WarpConst.warpPrivacyPolicyKey],\n                onKeyEvent: (node, event) => _handleKeyEvent(event, WarpConst.warpPrivacyPolicyKey),\n                child: const Gap(0.1),\n              ),\n              Text.rich(\n                t.dialogs.warpLicense.description(\n                  tos: (text) => TextSpan(\n                    text: text,\n                    style: TextStyle(\n                      color: focusStates[WarpConst.warpTermsOfServiceKey]!.value ? Colors.green : Colors.blue,\n                    ),\n                    recognizer: TapGestureRecognizer()\n                      ..onTap = () async {\n                        await UriUtils.tryLaunch(Uri.parse(Constants.cfWarpTermsOfService));\n                      },\n                  ),\n                  privacy: (text) => TextSpan(\n                    text: text,\n                    style: TextStyle(\n                      color: focusStates[WarpConst.warpPrivacyPolicyKey]!.value ? Colors.green : Colors.blue,\n                    ),\n                    recognizer: TapGestureRecognizer()\n                      ..onTap = () async {\n                        await UriUtils.tryLaunch(Uri.parse(Constants.cfWarpPrivacyPolicy));\n                      },\n                  ),\n                ),\n              ),\n            ],\n          ),\n        ),\n      ),\n      actions: [\n        TextButton(\n          onPressed: () {\n            context.pop(false);\n          },\n          child: Text(t.common.decline),\n        ),\n        TextButton(\n          onPressed: () {\n            context.pop(true);\n          },\n          child: Text(t.common.agree),\n        ),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/dialog/widgets/window_closing_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/preferences/actions_at_closing.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/features/window/notifier/window_notifier.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass WindowClosingDialog extends ConsumerStatefulWidget {\n  const WindowClosingDialog({super.key});\n\n  @override\n  ConsumerState<WindowClosingDialog> createState() => _WindowClosingDialogState();\n}\n\nclass _WindowClosingDialogState extends ConsumerState<WindowClosingDialog> {\n  bool remember = false;\n\n  @override\n  Widget build(BuildContext context) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    return AlertDialog(\n      title: Text(t.dialogs.windowClosing.alertMessage),\n      content: GestureDetector(\n        onTap: () => setState(() {\n          remember = !remember;\n        }),\n        behavior: HitTestBehavior.translucent,\n        child: Row(\n          children: [\n            Checkbox(\n              value: remember,\n              onChanged: (v) {\n                remember = v ?? remember;\n                setState(() {});\n              },\n            ),\n            const SizedBox(width: 16),\n            Text(t.dialogs.windowClosing.remember, style: const TextStyle(fontSize: 16)),\n          ],\n        ),\n      ),\n      actions: [\n        TextButton(\n          onPressed: () {\n            if (remember) {\n              ref.read(Preferences.actionAtClose.notifier).update(ActionsAtClosing.exit);\n            }\n            ref.read(windowNotifierProvider.notifier).exit();\n          },\n          child: Text(t.common.close),\n        ),\n        FilledButton(\n          onPressed: () async {\n            if (remember) {\n              ref.read(Preferences.actionAtClose.notifier).update(ActionsAtClosing.hide);\n            }\n            context.pop(false);\n            await ref.read(windowNotifierProvider.notifier).hide();\n          },\n          child: Text(t.common.hide),\n        ),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/go_router/go_router_notifier.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/router/go_router/refresh_listenable.dart';\nimport 'package:hiddify/core/router/go_router/routing_config_notifier.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'go_router_notifier.g.dart';\n\n// if 'stateful shell route' navigators not registered, this navigator key can be used for showing dialog or bottom sheet...\nfinal rootNavKey = GlobalKey<NavigatorState>(debugLabel: 'rootNav');\n\n@Riverpod(keepAlive: true)\nclass GoRouterNotifer extends _$GoRouterNotifer {\n  static final rConfig = ValueNotifier<RoutingConfig>(loadingConfig);\n  @override\n  GoRouter build() {\n    ref.listen(routingConfigNotifierProvider, (_, next) => rConfig.value = next);\n    return GoRouter.routingConfig(\n      initialLocation: '/home',\n      navigatorKey: rootNavKey,\n      routingConfig: rConfig,\n      refreshListenable: RefreshListenable(ref),\n      errorBuilder: (context, state) {\n        WidgetsBinding.instance.addPostFrameCallback((_) => context.goNamed('home'));\n        return const Material();\n      },\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/router/go_router/helper/active_breakpoint_notifier.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'active_breakpoint_notifier.g.dart';\n\n@Riverpod(keepAlive: true)\nclass ActiveBreakpointNotifier extends _$ActiveBreakpointNotifier {\n  @override\n  Breakpoints? build() {\n    return null;\n  }\n\n  void update(Breakpoints breakpoint) {\n    if (breakpoint == state) return;\n    state = breakpoint;\n  }\n}\n\n@riverpod\nbool? isMobileBreakpoint(Ref ref) {\n  final breakpoint = ref.watch(activeBreakpointNotifierProvider);\n  if (breakpoint == null) return null;\n  return breakpoint == Breakpoints.mobile;\n}\n\nclass Breakpoint {\n  static const sMobile = 0.0;\n  static const eMobile = 600.0;\n  static const sTable = 601.0;\n  static const eTable = 840.0;\n  static const sDesktop = 841.0;\n  static const eDesktop = double.infinity;\n\n  Breakpoint(BuildContext context) {\n    _width = MediaQuery.of(context).size.width;\n    if (_width < eMobile) {\n      activeBreakpoint = Breakpoints.mobile;\n    } else if (_width < eTable) {\n      activeBreakpoint = Breakpoints.tablet;\n    } else {\n      activeBreakpoint = Breakpoints.desktop;\n    }\n  }\n\n  late Breakpoints activeBreakpoint;\n  late double _width;\n\n  bool isMobile() => activeBreakpoint == Breakpoints.mobile;\n  bool isTablet() => activeBreakpoint == Breakpoints.tablet;\n  bool isDesktop() => activeBreakpoint == Breakpoints.desktop;\n\n  @override\n  String toString() {\n    return 'Breakpoint{name: ${activeBreakpoint.name}, width: $_width}';\n  }\n}\n\nenum Breakpoints { mobile, tablet, desktop }\n"
  },
  {
    "path": "lib/core/router/go_router/helper/custom_transition.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\n\nenum TransitionType { slide, fade }\n\nCustomTransitionPage<dynamic> customTransition(TransitionType transition, LocalKey pageKey, Widget child) =>\n    CustomTransitionPage(\n      key: pageKey,\n      child: child,\n      transitionDuration: const Duration(milliseconds: 150),\n      reverseTransitionDuration: const Duration(milliseconds: 100),\n      transitionsBuilder: (context, animation, _, child) => switch (transition) {\n        TransitionType.slide => SlideTransition(\n          position: Tween<Offset>(begin: const Offset(1.0, 0.0), end: Offset.zero).animate(animation),\n          textDirection: Directionality.of(context),\n          child: child,\n        ),\n        TransitionType.fade => FadeTransition(opacity: animation, child: child),\n      },\n    );\n"
  },
  {
    "path": "lib/core/router/go_router/helper/popup_count_notifier.dart",
    "content": "// import 'package:riverpod_annotation/riverpod_annotation.dart';\n\n// part 'popup_count_notifier.g.dart';\n\n// @Riverpod(keepAlive: true)\n// class PopupCountNotifier extends _$PopupCountNotifier {\n//   @override\n//   int build() => 0;\n\n//   void increase() => state += 1;\n\n//   void decrease() => state -= 1;\n// }\n"
  },
  {
    "path": "lib/core/router/go_router/refresh_listenable.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/router/deep_linking/my_app_links.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\n// For temporary storage of the link received from AppLinks.\nString newUrlFromAppLink = '';\n\nclass RefreshListenable extends ChangeNotifier {\n  RefreshListenable(this.ref) {\n    ref.listen(myAppLinksProvider, (_, next) {\n      if (next.value != null) {\n        newUrlFromAppLink = next.value!;\n        notifyListeners();\n      }\n    });\n    ref.listen(Preferences.introCompleted, (_, _) => notifyListeners());\n  }\n  final Ref ref;\n}\n"
  },
  {
    "path": "lib/core/router/go_router/routing_config_notifier.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/router/adaptive_layout/my_adaptive_layout.dart';\nimport 'package:hiddify/core/router/bottom_sheets/bottom_sheets_notifier.dart';\nimport 'package:hiddify/core/router/go_router/helper/active_breakpoint_notifier.dart';\nimport 'package:hiddify/core/router/go_router/helper/custom_transition.dart';\nimport 'package:hiddify/core/router/go_router/refresh_listenable.dart';\nimport 'package:hiddify/features/about/widget/about_page.dart';\nimport 'package:hiddify/features/home/widget/home_page.dart';\nimport 'package:hiddify/features/intro/widget/intro_page.dart';\nimport 'package:hiddify/features/log/overview/logs_page.dart';\nimport 'package:hiddify/features/per_app_proxy/overview/per_app_proxy_page.dart';\nimport 'package:hiddify/features/profile/details/profile_details_page.dart';\nimport 'package:hiddify/features/profile/notifier/active_profile_notifier.dart';\nimport 'package:hiddify/features/profile/overview/profiles_page.dart';\nimport 'package:hiddify/features/proxy/overview/proxies_overview_page.dart';\nimport 'package:hiddify/features/settings/overview/sections/dns_options_page.dart';\nimport 'package:hiddify/features/settings/overview/sections/general_page.dart';\nimport 'package:hiddify/features/settings/overview/sections/inbound_options_page.dart';\nimport 'package:hiddify/features/settings/overview/sections/route_options_page.dart';\nimport 'package:hiddify/features/settings/overview/sections/tls_tricks_page.dart';\nimport 'package:hiddify/features/settings/overview/sections/warp_options_page.dart';\nimport 'package:hiddify/features/settings/overview/settings_page.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'routing_config_notifier.g.dart';\n\n// each branch in go router has its own focus scope\nfinal branchesScope = <String, FocusScopeNode>{\n  'home': FocusScopeNode(),\n  'profiles': FocusScopeNode(),\n  'settings': FocusScopeNode(),\n  'logs': FocusScopeNode(),\n  'about': FocusScopeNode(),\n};\n\n// when the routing config is not yet initialized, this config is used\nfinal loadingConfig = RoutingConfig(\n  routes: <RouteBase>[GoRoute(path: '/home', builder: (context, state) => const Material())],\n);\n\nString getNameOfBranch(bool isMobileBreakpoint, bool showProfilesAction, int index) => isMobileBreakpoint\n    ? ['home', 'settings'][index]\n    : ['home', if (showProfilesAction) 'profiles', 'settings', 'logs', 'about'][index];\n\nint getIndexOfBranch(bool isMobileBreakpoint, bool showProfilesAction, String name) => isMobileBreakpoint\n    ? ['home', 'settings'].indexOf(name)\n    : ['home', if (showProfilesAction) 'profiles', 'settings', 'logs', 'about'].indexOf(name);\n\n@Riverpod(keepAlive: true)\nclass RoutingConfigNotifier extends _$RoutingConfigNotifier {\n  @override\n  RoutingConfig build() {\n    final isMobileBreakpoint = ref.watch(isMobileBreakpointProvider);\n    final bool showProfilesAction;\n    if (isMobileBreakpoint == true) {\n      showProfilesAction = false;\n    } else {\n      showProfilesAction = ref.watch(hasAnyProfileProvider).value ?? false;\n    }\n    if (isMobileBreakpoint == null) return loadingConfig;\n    return RoutingConfig(\n      redirect: (context, state) {\n        final introCompleted = ref.read(Preferences.introCompleted);\n        final isIntro = state.matchedLocation == '/intro';\n        // fix path-parameters for deep link\n        String? url;\n        if (LinkParser.protocols.contains(state.uri.scheme)) {\n          url = state.uri.toString();\n        } else if (PlatformUtils.isDesktop && newUrlFromAppLink.isNotEmpty) {\n          url = newUrlFromAppLink;\n          newUrlFromAppLink = '';\n        } else if (state.uri.queryParameters['url'] != null) {\n          url = state.uri.queryParameters['url'];\n        }\n\n        if (!introCompleted) {\n          return url != null ? '/intro?url=$url' : '/intro';\n        } else if (isIntro) {\n          if (url != null)\n            WidgetsBinding.instance.addPostFrameCallback(\n              (_) => ref.read(bottomSheetsNotifierProvider.notifier).showAddProfile(url: url),\n            );\n          return '/home';\n        } else if (url != null) {\n          WidgetsBinding.instance.addPostFrameCallback(\n            (_) => ref.read(bottomSheetsNotifierProvider.notifier).showAddProfile(url: url),\n          );\n          return '/home';\n        }\n        return null;\n      },\n      routes: <RouteBase>[\n        StatefulShellRoute.indexedStack(\n          builder: (_, _, navigationShell) => MyAdaptiveLayout(\n            navigationShell: navigationShell,\n            isMobileBreakpoint: isMobileBreakpoint,\n            showProfilesAction: showProfilesAction,\n          ),\n          branches: <StatefulShellBranch>[\n            StatefulShellBranch(\n              routes: <GoRoute>[\n                GoRoute(\n                  name: 'home',\n                  path: '/home',\n                  builder: (_, _) => FocusScope(node: branchesScope['home'], child: const HomePage()),\n                  routes: <GoRoute>[\n                    GoRoute(\n                      name: 'proxies',\n                      path: '/proxies',\n                      pageBuilder: (_, state) =>\n                          customTransition(TransitionType.fade, state.pageKey, const ProxiesOverviewPage()),\n                    ),\n                    if (isMobileBreakpoint)\n                      GoRoute(\n                        name: 'profileDetails',\n                        path: '/profile-details/:id',\n                        pageBuilder: (_, state) => customTransition(\n                          TransitionType.fade,\n                          state.pageKey,\n                          ProfileDetailsPage(id: state.pathParameters['id']!),\n                        ),\n                      ),\n                  ],\n                ),\n              ],\n            ),\n            if (showProfilesAction)\n              StatefulShellBranch(\n                routes: <GoRoute>[\n                  GoRoute(\n                    name: 'profiles',\n                    path: '/profiles',\n                    builder: (_, _) => FocusScope(node: branchesScope['profiles'], child: const ProfilesPage()),\n                    routes: <GoRoute>[\n                      GoRoute(\n                        name: 'profileDetails',\n                        path: '/profiles/:id',\n                        pageBuilder: (_, state) => customTransition(\n                          TransitionType.fade,\n                          state.pageKey,\n                          ProfileDetailsPage(id: state.pathParameters['id']!),\n                        ),\n                      ),\n                    ],\n                  ),\n                ],\n              ),\n            StatefulShellBranch(\n              routes: <GoRoute>[\n                GoRoute(\n                  name: 'settings',\n                  path: '/settings',\n                  builder: (context, _) => FocusScope(\n                    node: branchesScope['settings'],\n                    child: PopScope(\n                      canPop: false,\n                      onPopInvokedWithResult: (_, _) => context.goNamed('home'),\n                      child: SettingsPage(),\n                    ),\n                  ),\n                  routes: <GoRoute>[\n                    GoRoute(\n                      name: 'general',\n                      path: '/general',\n                      pageBuilder: (_, state) =>\n                          customTransition(TransitionType.slide, state.pageKey, const GeneralPage()),\n                    ),\n                    GoRoute(\n                      name: 'routeOptions',\n                      path: '/route-options',\n                      pageBuilder: (_, state) =>\n                          customTransition(TransitionType.slide, state.pageKey, const RouteOptionsPage()),\n                      routes: <GoRoute>[\n                        GoRoute(\n                          name: 'perAppProxy',\n                          path: '/per-app-proxy',\n                          pageBuilder: (_, state) =>\n                              customTransition(TransitionType.slide, state.pageKey, const PerAppProxyPage()),\n                        ),\n                      ],\n                    ),\n                    GoRoute(\n                      name: 'dnsOptions',\n                      path: '/dns-options',\n                      pageBuilder: (_, state) =>\n                          customTransition(TransitionType.slide, state.pageKey, const DnsOptionsPage()),\n                    ),\n                    GoRoute(\n                      name: 'inboundOptions',\n                      path: '/inbound-options',\n                      pageBuilder: (_, state) =>\n                          customTransition(TransitionType.slide, state.pageKey, const InboundOptionsPage()),\n                    ),\n                    GoRoute(\n                      name: 'tlsTricks',\n                      path: '/tls-tricks',\n                      pageBuilder: (_, state) =>\n                          customTransition(TransitionType.slide, state.pageKey, const TlsTricksPage()),\n                    ),\n                    GoRoute(\n                      name: 'warpOptions',\n                      path: '/warp-options',\n                      pageBuilder: (_, state) =>\n                          customTransition(TransitionType.slide, state.pageKey, const WarpOptionsPage()),\n                    ),\n                    if (isMobileBreakpoint) ...[\n                      GoRoute(\n                        name: 'logs',\n                        path: '/logs',\n                        pageBuilder: (_, state) =>\n                            customTransition(TransitionType.slide, state.pageKey, const LogsPage()),\n                      ),\n                      GoRoute(\n                        name: 'about',\n                        path: '/about',\n                        pageBuilder: (_, state) =>\n                            customTransition(TransitionType.slide, state.pageKey, const AboutPage()),\n                      ),\n                    ],\n                  ],\n                ),\n              ],\n            ),\n            if (!isMobileBreakpoint) ...[\n              StatefulShellBranch(\n                routes: <GoRoute>[\n                  GoRoute(\n                    name: 'logs',\n                    path: '/logs',\n                    builder: (_, _) => FocusScope(node: branchesScope['logs'], child: const LogsPage()),\n                  ),\n                ],\n              ),\n              StatefulShellBranch(\n                routes: <GoRoute>[\n                  GoRoute(\n                    name: 'about',\n                    path: '/about',\n                    builder: (_, _) => FocusScope(node: branchesScope['about'], child: const AboutPage()),\n                  ),\n                ],\n              ),\n            ],\n          ],\n        ),\n        GoRoute(name: 'intro', path: '/intro', builder: (_, _) => const IntroPage()),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/theme/app_theme.dart",
    "content": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:hiddify/core/theme/app_theme_mode.dart';\nimport 'package:hiddify/core/theme/theme_extensions.dart';\n\nclass AppTheme {\n  AppTheme(this.mode, this.fontFamily);\n  final AppThemeMode mode;\n  final String fontFamily;\n\n  ThemeData lightTheme(ColorScheme? lightColorScheme) {\n    final ColorScheme scheme = lightColorScheme ?? ColorScheme.fromSeed(seedColor: const Color(0xFF293CA0));\n    return ThemeData(\n      useMaterial3: true,\n      colorScheme: scheme,\n      fontFamily: fontFamily,\n      extensions: const <ThemeExtension<dynamic>>{ConnectionButtonTheme.light},\n    );\n  }\n\n  ThemeData darkTheme(ColorScheme? darkColorScheme) {\n    final ColorScheme scheme =\n        darkColorScheme ?? ColorScheme.fromSeed(seedColor: const Color(0xFF293CA0), brightness: Brightness.dark);\n    return ThemeData(\n      useMaterial3: true,\n      colorScheme: scheme,\n      scaffoldBackgroundColor: mode.trueBlack ? Colors.black : scheme.background,\n      fontFamily: fontFamily,\n      extensions: const <ThemeExtension<dynamic>>{ConnectionButtonTheme.light},\n    );\n  }\n\n  CupertinoThemeData cupertinoThemeData(bool sysDark, ColorScheme? lightColorScheme, ColorScheme? darkColorScheme) {\n    final bool isDark = switch (mode) {\n      AppThemeMode.system => sysDark,\n      AppThemeMode.light => false,\n      AppThemeMode.dark => true,\n      AppThemeMode.black => true,\n    };\n    final def = CupertinoThemeData(brightness: isDark ? Brightness.dark : Brightness.light);\n    // final def = CupertinoThemeData(brightness: Brightness.dark);\n\n    // return def;\n    final defaultMaterialTheme = isDark ? darkTheme(darkColorScheme) : lightTheme(lightColorScheme);\n    return MaterialBasedCupertinoThemeData(\n      materialTheme: defaultMaterialTheme.copyWith(\n        cupertinoOverrideTheme: def.copyWith(\n          textTheme: CupertinoTextThemeData(\n            textStyle: def.textTheme.textStyle.copyWith(fontFamily: fontFamily),\n            actionTextStyle: def.textTheme.actionTextStyle.copyWith(fontFamily: fontFamily),\n            navActionTextStyle: def.textTheme.navActionTextStyle.copyWith(fontFamily: fontFamily),\n            navTitleTextStyle: def.textTheme.navTitleTextStyle.copyWith(fontFamily: fontFamily),\n            navLargeTitleTextStyle: def.textTheme.navLargeTitleTextStyle.copyWith(fontFamily: fontFamily),\n            pickerTextStyle: def.textTheme.pickerTextStyle.copyWith(fontFamily: fontFamily),\n            dateTimePickerTextStyle: def.textTheme.dateTimePickerTextStyle.copyWith(fontFamily: fontFamily),\n            tabLabelTextStyle: def.textTheme.tabLabelTextStyle.copyWith(fontFamily: fontFamily),\n          ).copyWith(),\n          barBackgroundColor: def.barBackgroundColor,\n          scaffoldBackgroundColor: def.scaffoldBackgroundColor,\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/theme/app_theme_mode.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\n\nenum AppThemeMode {\n  system,\n  light,\n  dark,\n  black;\n\n  String present(TranslationsEn t) => switch (this) {\n    system => t.pages.settings.general.themeModes.system,\n    light => t.pages.settings.general.themeModes.light,\n    dark => t.pages.settings.general.themeModes.dark,\n    black => t.pages.settings.general.themeModes.black,\n  };\n\n  ThemeMode get flutterThemeMode => switch (this) {\n    system => ThemeMode.system,\n    light => ThemeMode.light,\n    dark => ThemeMode.dark,\n    black => ThemeMode.dark,\n  };\n\n  bool get trueBlack => this == black;\n}\n"
  },
  {
    "path": "lib/core/theme/theme_extensions.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass ConnectionButtonTheme extends ThemeExtension<ConnectionButtonTheme> {\n  const ConnectionButtonTheme({this.idleColor, this.connectedColor});\n\n  final Color? idleColor;\n  final Color? connectedColor;\n\n  static const ConnectionButtonTheme light = ConnectionButtonTheme(\n    idleColor: Color(0xFF4a4d8b),\n    connectedColor: Color(0xFF44a334),\n  );\n\n  @override\n  ThemeExtension<ConnectionButtonTheme> copyWith({Color? idleColor, Color? connectedColor}) => ConnectionButtonTheme(\n    idleColor: idleColor ?? this.idleColor,\n    connectedColor: connectedColor ?? this.connectedColor,\n  );\n\n  @override\n  ThemeExtension<ConnectionButtonTheme> lerp(covariant ThemeExtension<ConnectionButtonTheme>? other, double t) {\n    if (other is! ConnectionButtonTheme) {\n      return this;\n    }\n    return ConnectionButtonTheme(\n      idleColor: Color.lerp(idleColor, other.idleColor, t),\n      connectedColor: Color.lerp(connectedColor, other.connectedColor, t),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/theme/theme_preferences.dart",
    "content": "import 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/core/theme/app_theme_mode.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'theme_preferences.g.dart';\n\n@Riverpod(keepAlive: true)\nclass ThemePreferences extends _$ThemePreferences {\n  @override\n  AppThemeMode build() {\n    final persisted = ref.watch(sharedPreferencesProvider).requireValue.getString(\"theme_mode\");\n    if (persisted == null) return AppThemeMode.system;\n    return AppThemeMode.values.byName(persisted);\n  }\n\n  Future<void> changeThemeMode(AppThemeMode value) async {\n    state = value;\n    await ref.read(sharedPreferencesProvider).requireValue.setString(\"theme_mode\", value.name);\n  }\n}\n"
  },
  {
    "path": "lib/core/utils/exception_handler.dart",
    "content": "import 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:rxdart/rxdart.dart';\n\nmixin ExceptionHandler implements LoggerMixin {\n  TaskEither<F, R> exceptionHandler<F, R>(\n    Future<Either<F, R>> Function() run,\n    F Function(Object error, StackTrace stackTrace) onError,\n  ) {\n    return TaskEither(() async {\n      try {\n        return await run();\n      } catch (error, stackTrace) {\n        return Left(onError(error, stackTrace));\n      }\n    });\n  }\n}\n\nextension StreamExceptionHandler<R extends Object?> on Stream<R> {\n  Stream<Either<F, R>> handleExceptions<F>(F Function(Object error, StackTrace stackTrace) onError) {\n    return map(right<F, R>).onErrorReturnWith((error, stackTrace) {\n      return Left(onError(error, stackTrace));\n    });\n  }\n}\n\nextension TaskEitherExceptionHandler<F, R> on TaskEither<F, R> {\n  TaskEither<F, R> handleExceptions(F Function(Object error, StackTrace stackTrace) onError) {\n    return TaskEither(() async {\n      try {\n        return await run();\n      } catch (error, stackTrace) {\n        return Left(onError(error, stackTrace));\n      }\n    });\n  }\n}\n"
  },
  {
    "path": "lib/core/utils/ffi_utils.dart",
    "content": "import 'dart:ffi';\n\nimport 'package:ffi/ffi.dart';\n\nR withMemory<R, T extends NativeType>(int size, R Function(Pointer<T> memory) action) {\n  final memory = calloc<Int8>(size);\n  try {\n    return action(memory.cast());\n  } finally {\n    calloc.free(memory);\n  }\n}\n"
  },
  {
    "path": "lib/core/utils/ip_utils.dart",
    "content": "const String fallbackObscuredAddress = \"*.*.*.*\";\n\nString obscureIp(String ip) {\n  try {\n    if (ip.contains(\".\")) {\n      final splits = ip.split(\".\");\n      return \"${splits.first}.*.*.${splits.last}\";\n    } else if (ip.contains(\":\")) {\n      final splits = ip.split(\":\");\n      return [splits.first, ...splits.sublist(1).map((part) => \"*\" * part.length)].join(\":\");\n    }\n    // ignore: empty_catches\n  } catch (e) {}\n  return fallbackObscuredAddress;\n}\n"
  },
  {
    "path": "lib/core/utils/json_converters.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\n\nclass IntervalInSecondsConverter implements JsonConverter<Duration, int> {\n  const IntervalInSecondsConverter();\n\n  @override\n  Duration fromJson(int json) => Duration(seconds: json);\n\n  @override\n  int toJson(Duration object) => object.inSeconds;\n}\n"
  },
  {
    "path": "lib/core/utils/laststeam.dart",
    "content": "import 'dart:async';\n\nclass LastStream<T> {\n  final Stream<T> _source;\n  T? _latest;\n  bool _hasValue = false;\n  late final StreamSubscription<T> _sub;\n  final List<Completer<T>> _waiters = [];\n\n  LastStream(Stream<T> source) : _source = source {\n    _sub = _source.listen((event) {\n      _latest = event;\n      _hasValue = true;\n      // Complete all waiting futures\n      for (final completer in _waiters) {\n        if (!completer.isCompleted) completer.complete(event);\n      }\n      _waiters.clear();\n    });\n  }\n\n  void clean() {\n    _latest = null;\n    _hasValue = false;\n  }\n\n  /// Returns the latest value if available,\n  /// otherwise waits up to [timeout] for one.\n  Future<T> get({Duration? timeout}) async {\n    if (_hasValue) return _latest as T;\n\n    final completer = Completer<T>();\n    _waiters.add(completer);\n\n    if (timeout != null) {\n      return completer.future.timeout(\n        timeout,\n        onTimeout: () {\n          _waiters.remove(completer);\n          throw TimeoutException('No value received in $timeout');\n        },\n      );\n    }\n\n    return completer.future;\n  }\n\n  /// Dispose the listener and clear resources.\n  Future<void> close() async {\n    await _sub.cancel();\n    for (final c in _waiters) {\n      if (!c.isCompleted) {\n        c.completeError(StateError('Stream closed'));\n      }\n    }\n    _waiters.clear();\n  }\n}\n"
  },
  {
    "path": "lib/core/utils/preferences_utils.dart",
    "content": "import 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\nclass PreferencesEntry<T, P> with InfraLogger {\n  PreferencesEntry({required this.preferences, required this.key, required this.defaultValue, this.mapFrom, this.mapTo, this.validator});\n\n  final SharedPreferences preferences;\n  final String key;\n  final T defaultValue;\n  final T Function(P value)? mapFrom;\n  final P Function(T value)? mapTo;\n  final bool Function(T value)? validator;\n\n  T read() {\n    try {\n      // loggy.debug(\"getting persisted preference [$key]($T)\");\n      final T value;\n      if (mapFrom != null) {\n        final persisted = preferences.get(key) as P?;\n        if (persisted == null) {\n          value = defaultValue;\n        } else {\n          value = mapFrom!(persisted);\n        }\n      } else if (T == List<String>) {\n        final storedValue = preferences.getString(key);\n        value = storedValue == null ? defaultValue : storedValue.split(\";\") as T;\n      } else {\n        value = preferences.get(key) as T? ?? defaultValue;\n      }\n\n      if (validator?.call(value) ?? true) return value;\n      return defaultValue;\n    } catch (e, stackTrace) {\n      loggy.warning(\"error getting preference[$key]: $e\", e, stackTrace);\n      return defaultValue;\n    }\n  }\n\n  Future<bool> write(T value) async {\n    Object? mapped = value;\n    if (mapTo != null) {\n      mapped = mapTo!(value);\n    }\n    loggy.debug(\"updating preference [$key]($T) to [$mapped]\");\n    try {\n      if (!(validator?.call(value) ?? true)) {\n        loggy.warning(\"invalid value [$value] for preference [$key]($T)\");\n        return false;\n      }\n\n      return switch (mapped) {\n        final String value => await preferences.setString(key, value),\n        final bool value => await preferences.setBool(key, value),\n        final int value => await preferences.setInt(key, value),\n        final double value => await preferences.setDouble(key, value),\n        final List<String> value => await preferences.setString(key, value.join(\";\")),\n        _ => throw const FormatException(\"Invalid Type\"),\n      };\n    } catch (e, stackTrace) {\n      loggy.warning(\"error updating preference[$key]: $e\", e, stackTrace);\n      return false;\n    }\n  }\n\n  Future<T?> writeRaw(P input) async {\n    final T value;\n    if (mapFrom != null) {\n      value = mapFrom!(input);\n    } else {\n      value = input as T;\n    }\n    if (await write(value)) return value;\n    return null;\n  }\n\n  Future<void> remove() async {\n    try {\n      await preferences.remove(key);\n    } catch (e, stackTrace) {\n      loggy.warning(\"error removing preference[$key]: $e\", e, stackTrace);\n    }\n  }\n}\n\nclass PreferencesNotifier<T, P> extends StateNotifier<T> {\n  PreferencesNotifier._({required Ref ref, required this.entry, this.overrideValue, this.possibleValues}) : _ref = ref, super(overrideValue ?? entry.read());\n\n  final Ref _ref;\n  final PreferencesEntry<T, P> entry;\n  final T? overrideValue;\n  final List<T>? possibleValues;\n\n  static StateNotifierProvider<PreferencesNotifier<T, P>, T> create<T, P>(\n    String key,\n    T defaultValue, {\n    T Function(Ref ref)? defaultValueFunction,\n    T Function(P value)? mapFrom,\n    P Function(T value)? mapTo,\n    bool Function(T value)? validator,\n    T? overrideValue,\n    List<T>? possibleValues,\n  }) => StateNotifierProvider(\n    (ref) => PreferencesNotifier._(\n      ref: ref,\n      entry: PreferencesEntry<T, P>(preferences: ref.read(sharedPreferencesProvider).requireValue, key: key, defaultValue: defaultValueFunction?.call(ref) ?? defaultValue, mapFrom: mapFrom, mapTo: mapTo, validator: validator),\n      overrideValue: overrideValue,\n      possibleValues: possibleValues,\n    ),\n  );\n\n  static AutoDisposeStateNotifierProvider<PreferencesNotifier<T, P>, T> createAutoDispose<T, P>(String key, T defaultValue, {T Function(P value)? mapFrom, P Function(T value)? mapTo, bool Function(T value)? validator, T? overrideValue}) =>\n      StateNotifierProvider.autoDispose(\n        (ref) => PreferencesNotifier._(\n          ref: ref,\n          entry: PreferencesEntry<T, P>(preferences: ref.read(sharedPreferencesProvider).requireValue, key: key, defaultValue: defaultValue, mapFrom: mapFrom, mapTo: mapTo, validator: validator),\n          overrideValue: overrideValue,\n        ),\n      );\n\n  P raw() {\n    final value = overrideValue ?? state;\n    if (entry.mapTo != null) return entry.mapTo!(value);\n    return value as P;\n  }\n\n  Future<void> updateRaw(P input) async {\n    final value = await entry.writeRaw(input);\n    if (value != null) state = value;\n  }\n\n  Future<void> update(T value) async {\n    if (await entry.write(value)) state = value;\n  }\n\n  Future<void> reset() async {\n    await entry.remove();\n    _ref.invalidateSelf();\n  }\n}\n"
  },
  {
    "path": "lib/core/utils/throttler.dart",
    "content": "import 'package:flutter/foundation.dart';\n\nclass Throttler {\n  Throttler(this.throttleFor);\n\n  final Duration throttleFor;\n  DateTime? _lastCall;\n\n  void call(VoidCallback callback) {\n    if (_lastCall == null || DateTime.now().difference(_lastCall!) > throttleFor) {\n      callback();\n      _lastCall = DateTime.now();\n    }\n  }\n}\n"
  },
  {
    "path": "lib/core/widget/adaptive_icon.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\n\nclass AdaptiveIcon {\n  AdaptiveIcon(BuildContext context) : platform = Theme.of(context).platform;\n\n  final TargetPlatform platform;\n\n  IconData get more => switch (platform) {\n    TargetPlatform.iOS || TargetPlatform.macOS => FluentIcons.more_horizontal_24_regular,\n    _ => FluentIcons.more_vertical_24_regular,\n  };\n\n  IconData get share => switch (platform) {\n    TargetPlatform.android => FluentIcons.share_android_24_regular,\n    TargetPlatform.iOS || TargetPlatform.macOS => FluentIcons.share_ios_24_regular,\n    _ => FluentIcons.share_24_regular,\n  };\n}\n"
  },
  {
    "path": "lib/core/widget/adaptive_menu.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\ntypedef AdaptiveMenuBuilder = Widget Function(BuildContext context, void Function() toggleVisibility, Widget? child);\n\nclass AdaptiveMenuItem<T> {\n  AdaptiveMenuItem({required this.title, this.icon, this.onTap, this.isSelected, this.subItems});\n\n  final String title;\n  final IconData? icon;\n  final T Function()? onTap;\n  final bool? isSelected;\n  final List<AdaptiveMenuItem>? subItems;\n\n  (String, IconData?, T Function()?, bool?, List<AdaptiveMenuItem>?) _equality() =>\n      (title, icon, onTap, isSelected, subItems);\n\n  @override\n  bool operator ==(covariant AdaptiveMenuItem other) {\n    if (identical(this, other)) return true;\n    return other._equality() == _equality();\n  }\n\n  @override\n  int get hashCode => _equality().hashCode;\n}\n\nclass AdaptiveMenu extends HookConsumerWidget {\n  const AdaptiveMenu({super.key, required this.items, required this.builder, required this.child});\n\n  final Iterable<AdaptiveMenuItem> items;\n  final AdaptiveMenuBuilder builder;\n  final Widget? child;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    List<Widget> buildMenuItems(Iterable<AdaptiveMenuItem> scopeItems) {\n      final menuItems = <Widget>[];\n      for (final item in scopeItems) {\n        if (item.subItems != null) {\n          final subItems = buildMenuItems(item.subItems!);\n          menuItems.add(\n            SubmenuButton(\n              menuChildren: subItems,\n              leadingIcon: item.icon != null ? Icon(item.icon) : null,\n              child: Text(item.title),\n            ),\n          );\n        } else {\n          menuItems.add(\n            MenuItemButton(\n              leadingIcon: item.icon != null ? Icon(item.icon) : null,\n              onPressed: item.onTap,\n              child: Text(item.title),\n            ),\n          );\n        }\n      }\n      return menuItems;\n    }\n\n    return MenuAnchor(\n      builder: (context, controller, child) => builder(context, () {\n        if (controller.isOpen) {\n          controller.close();\n        } else {\n          controller.open();\n        }\n      }, child),\n      menuChildren: buildMenuItems(items),\n      child: child,\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/widget/animated_text.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/model/constants.dart';\n\nclass AnimatedText extends Text {\n  const AnimatedText(\n    super.data, {\n    super.key,\n    super.style,\n    this.duration = kAnimationDuration,\n    this.size = true,\n    this.slide = true,\n  });\n\n  final Duration duration;\n  final bool size;\n  final bool slide;\n\n  @override\n  Widget build(BuildContext context) {\n    return AnimatedSwitcher(\n      duration: duration,\n      transitionBuilder: (child, animation) {\n        child = FadeTransition(opacity: animation, child: child);\n        if (size) {\n          child = SizeTransition(\n            axis: Axis.horizontal,\n            fixedCrossAxisSizeFactor: 1,\n            sizeFactor: Tween<double>(begin: 0.88, end: 1).animate(animation),\n            child: child,\n          );\n        }\n        if (slide) {\n          child = SlideTransition(\n            position: Tween<Offset>(begin: const Offset(0.0, -0.2), end: Offset.zero).animate(animation),\n            child: child,\n          );\n        }\n        return child;\n      },\n      child: Text(data!, key: ValueKey<String>(data!), style: style),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/widget/animated_visibility.dart",
    "content": "import 'package:flutter/widgets.dart';\n\nclass AnimatedVisibility extends StatelessWidget {\n  const AnimatedVisibility({\n    super.key,\n    required this.visible,\n    this.axis = Axis.horizontal,\n    this.padding = EdgeInsets.zero,\n    required this.child,\n  });\n\n  final bool visible;\n  final Axis axis;\n  final EdgeInsets padding;\n  final Widget child;\n\n  @override\n  Widget build(BuildContext context) {\n    final replacement = axis == Axis.vertical ? const SizedBox(width: double.infinity) : const SizedBox.shrink();\n\n    return AnimatedSwitcher(\n      duration: const Duration(milliseconds: 200),\n      transitionBuilder: (child, animation) => SizeTransition(\n        sizeFactor: animation,\n        child: FadeTransition(opacity: animation, child: child),\n      ),\n      child: visible\n          ? AnimatedPadding(padding: padding, duration: const Duration(milliseconds: 200), child: child)\n          : replacement,\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/widget/shimmer_skeleton.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter_animate/flutter_animate.dart';\nimport 'package:hiddify/core/widget/skeleton_widget.dart';\n\nclass ShimmerSkeleton extends StatelessWidget {\n  const ShimmerSkeleton({\n    this.width,\n    this.height,\n    this.widthFactor,\n    this.heightFactor,\n    this.color,\n    this.duration = const Duration(seconds: 1),\n    super.key,\n  });\n\n  final double? width;\n  final double? height;\n  final double? widthFactor;\n  final double? heightFactor;\n  final Color? color;\n  final Duration duration;\n\n  @override\n  Widget build(BuildContext context) {\n    return Skeleton(width: width, height: height, widthFactor: widthFactor, heightFactor: heightFactor)\n        .animate(onPlay: (controller) => controller.loop())\n        .shimmer(duration: duration, angle: 45, color: color ?? Theme.of(context).colorScheme.secondary);\n  }\n}\n"
  },
  {
    "path": "lib/core/widget/skeleton_widget.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass Skeleton extends StatelessWidget {\n  const Skeleton({\n    this.width,\n    this.height,\n    this.widthFactor,\n    this.heightFactor,\n    this.shape = BoxShape.rectangle,\n    this.alignment = AlignmentDirectional.center,\n  });\n\n  final double? width;\n  final double? height;\n  final double? widthFactor;\n  final double? heightFactor;\n  final BoxShape shape;\n  final AlignmentGeometry alignment;\n\n  @override\n  Widget build(BuildContext context) {\n    final theme = Theme.of(context);\n\n    return FractionallySizedBox(\n      widthFactor: widthFactor,\n      heightFactor: heightFactor,\n      alignment: alignment,\n      child: Container(\n        width: width,\n        height: height,\n        decoration: BoxDecoration(\n          borderRadius: BorderRadius.circular(8),\n          shape: shape,\n          color: theme.hintColor.withOpacity(.16),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/core/widget/spaced_list_widget.dart",
    "content": "import 'package:flutter/widgets.dart';\n\nextension SpacedWidgets on List<Widget> {\n  List<Widget> spaceBy({double? width, double? height}) => [\n    for (int i = 0; i < length; i++) ...[if (i > 0) SizedBox(width: width, height: height), this[i]],\n  ];\n}\n"
  },
  {
    "path": "lib/core/widget/tip_card.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\n\nclass TipCard extends StatelessWidget {\n  const TipCard({required this.message, super.key});\n\n  final String message;\n\n  @override\n  Widget build(BuildContext context) {\n    return Card(\n      margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),\n      child: Row(\n        children: [\n          const Padding(padding: EdgeInsets.all(8.0), child: Icon(FluentIcons.lightbulb_24_regular)),\n          Expanded(\n            child: Column(\n              crossAxisAlignment: CrossAxisAlignment.stretch,\n              children: [\n                Padding(padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), child: Text(message)),\n              ],\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/about/widget/about_page.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/app_info/app_info_provider.dart';\nimport 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/core/widget/adaptive_icon.dart';\nimport 'package:hiddify/features/app_update/notifier/app_update_notifier.dart';\nimport 'package:hiddify/features/app_update/notifier/app_update_state.dart';\nimport 'package:hiddify/gen/assets.gen.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass AboutPage extends HookConsumerWidget {\n  const AboutPage({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final appInfo = ref.watch(appInfoProvider).requireValue;\n    final appUpdate = ref.watch(appUpdateNotifierProvider);\n\n    ref.listen(appUpdateNotifierProvider, (_, next) async {\n      if (!context.mounted) return;\n      switch (next) {\n        case AppUpdateStateAvailable(:final versionInfo) || AppUpdateStateIgnored(:final versionInfo):\n          return await ref\n              .read(dialogNotifierProvider.notifier)\n              .showNewVersion(currentVersion: appInfo.presentVersion, newVersion: versionInfo, canIgnore: false);\n        case AppUpdateStateError(:final error):\n          return CustomToast.error(t.presentShortError(error)).show(context);\n        case AppUpdateStateNotAvailable():\n          return CustomToast.success(t.pages.about.notAvailableMsg).show(context);\n      }\n    });\n\n    final conditionalTiles = [\n      if (appInfo.release.allowCustomUpdateChecker)\n        ListTile(\n          title: Text(t.pages.about.checkForUpdate),\n          trailing: switch (appUpdate) {\n            AppUpdateStateChecking() => const SizedBox(width: 24, height: 24, child: CircularProgressIndicator()),\n            _ => const Icon(FluentIcons.arrow_sync_24_regular),\n          },\n          onTap: () async {\n            await ref.read(appUpdateNotifierProvider.notifier).check();\n          },\n        ),\n      if (PlatformUtils.isDesktop)\n        ListTile(\n          title: Text(t.pages.about.openWorkingDir),\n          trailing: const Icon(FluentIcons.open_folder_24_regular),\n          onTap: () async {\n            final path = ref.watch(appDirectoriesProvider).requireValue.workingDir.uri;\n            await UriUtils.tryLaunch(path);\n          },\n        ),\n    ];\n\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(t.pages.about.title),\n        actions: [\n          PopupMenuButton(\n            icon: Icon(AdaptiveIcon(context).more),\n            itemBuilder: (context) {\n              return [\n                PopupMenuItem(\n                  child: Text(t.common.addToClipboard),\n                  onTap: () {\n                    Clipboard.setData(ClipboardData(text: appInfo.format()));\n                  },\n                ),\n              ];\n            },\n          ),\n          const Gap(8),\n        ],\n      ),\n      body: CustomScrollView(\n        slivers: [\n          SliverToBoxAdapter(\n            child: Padding(\n              padding: const EdgeInsets.all(16),\n              child: Row(\n                mainAxisAlignment: MainAxisAlignment.center,\n                children: [\n                  Assets.images.logo.svg(width: 64, height: 64),\n                  const Gap(16),\n                  Column(\n                    crossAxisAlignment: CrossAxisAlignment.start,\n                    children: [\n                      Text(t.common.appTitle, style: Theme.of(context).textTheme.titleLarge),\n                      const Gap(4),\n                      Text(\"${t.common.version} ${appInfo.presentVersion}\"),\n                    ],\n                  ),\n                ],\n              ),\n            ),\n          ),\n          SliverList(\n            delegate: SliverChildListDelegate([\n              ...conditionalTiles,\n              if (conditionalTiles.isNotEmpty) const Divider(),\n              ListTile(\n                title: Text(t.pages.about.sourceCode),\n                trailing: const Icon(FluentIcons.open_24_regular),\n                onTap: () async {\n                  await UriUtils.tryLaunch(Uri.parse(Constants.githubUrl));\n                },\n              ),\n              ListTile(\n                title: Text(t.pages.about.telegramChannel),\n                trailing: const Icon(FluentIcons.open_24_regular),\n                onTap: () async {\n                  await UriUtils.tryLaunch(Uri.parse(Constants.telegramChannelUrl));\n                },\n              ),\n              ListTile(\n                title: Text(t.pages.about.termsAndConditions),\n                trailing: const Icon(FluentIcons.open_24_regular),\n                onTap: () async {\n                  await UriUtils.tryLaunch(Uri.parse(Constants.termsAndConditionsUrl));\n                },\n              ),\n              ListTile(\n                title: Text(t.pages.about.privacyPolicy),\n                trailing: const Icon(FluentIcons.open_24_regular),\n                onTap: () async {\n                  await UriUtils.tryLaunch(Uri.parse(Constants.privacyPolicyUrl));\n                },\n              ),\n            ]),\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/app/widget/app.dart",
    "content": "import 'package:accessibility_tools/accessibility_tools.dart';\nimport 'package:dynamic_color/dynamic_color.dart';\nimport 'package:flutter/foundation.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:flutter_localizations/flutter_localizations.dart';\nimport 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/core/localization/locale_extensions.dart';\nimport 'package:hiddify/core/localization/locale_preferences.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/router/go_router/go_router_notifier.dart';\nimport 'package:hiddify/core/router/go_router/helper/active_breakpoint_notifier.dart';\nimport 'package:hiddify/core/theme/app_theme.dart';\nimport 'package:hiddify/core/theme/theme_preferences.dart';\nimport 'package:hiddify/features/app_update/notifier/app_update_notifier.dart';\nimport 'package:hiddify/features/connection/widget/connection_wrapper.dart';\nimport 'package:hiddify/features/per_app_proxy/overview/per_app_proxy_service_notifier.dart';\nimport 'package:hiddify/features/profile/notifier/profiles_update_notifier.dart';\nimport 'package:hiddify/features/shortcut/shortcut_wrapper.dart';\nimport 'package:hiddify/features/system_tray/notifier/system_tray_notifier.dart';\nimport 'package:hiddify/features/window/widget/window_wrapper.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service_provider.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:toastification/toastification.dart';\nimport 'package:upgrader/upgrader.dart';\n\nbool _debugAccessibility = false;\nbool isOnPauseCalled = false;\n\nclass App extends HookConsumerWidget with WidgetsBindingObserver, PresLogger {\n  const App({super.key});\n\n  void onInactive(WidgetRef ref) {\n    onPause(ref);\n  }\n\n  void onPause(WidgetRef ref) {\n    if (PlatformUtils.isDesktop) return;\n    isOnPauseCalled = true;\n    ref.read(hiddifyCoreServiceProvider).closeFront();\n  }\n\n  void onResume(WidgetRef ref) {\n    // if (PlatformUtils.isDesktop) return;\n    ref.read(hiddifyCoreServiceProvider).init();\n\n    WidgetsBinding.instance.addPostFrameCallback((_) {\n      if (isOnPauseCalled && PlatformUtils.isAndroid) ref.invalidate(perAppProxyServiceProvider);\n      isOnPauseCalled = false;\n    });\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    setupStateListener(ref);\n    final router = ref.watch(goRouterNotiferProvider);\n    final locale = ref.watch(localePreferencesProvider);\n    final themeMode = ref.watch(themePreferencesProvider);\n    final theme = AppTheme(themeMode, locale.preferredFontFamily);\n    final upgrader = ref.watch(upgraderProvider);\n    final activeBreakpoint = Breakpoint(context).activeBreakpoint;\n\n    ref.listen(foregroundProfilesUpdateNotifierProvider, (_, _) {});\n    if (PlatformUtils.isAndroid) ref.listen(perAppProxyServiceProvider, (_, _) {});\n    if (PlatformUtils.isDesktop) ref.listen(systemTrayNotifierProvider, (_, _) {});\n\n    // updating ActiveBreakpointNotifier value\n    useEffect(() {\n      WidgetsBinding.instance.addPostFrameCallback((_) {\n        ref.read(activeBreakpointNotifierProvider.notifier).update(activeBreakpoint);\n      });\n      return null;\n    }, [activeBreakpoint]);\n    return WindowWrapper(\n      ShortcutWrapper(\n        ToastificationWrapper(\n          child: ConnectionWrapper(\n            DynamicColorBuilder(\n              builder: (ColorScheme? lightColorScheme, ColorScheme? darkColorScheme) {\n                return MaterialApp.router(\n                  routerConfig: router,\n                  locale: locale.flutterLocale,\n                  supportedLocales: AppLocaleUtils.supportedLocales,\n                  localizationsDelegates: GlobalMaterialLocalizations.delegates,\n                  debugShowCheckedModeBanner: false,\n                  themeMode: themeMode.flutterThemeMode,\n                  theme: theme.lightTheme(lightColorScheme),\n                  darkTheme: theme.darkTheme(darkColorScheme),\n                  title: Constants.appName,\n                  builder: (context, child) {\n                    final theme = Theme.of(context);\n                    child = UpgradeAlert(\n                      upgrader: upgrader,\n                      navigatorKey: router.routerDelegate.navigatorKey,\n                      child: child ?? const SizedBox(),\n                    );\n                    if (kDebugMode && _debugAccessibility) {\n                      return AccessibilityTools(checkFontOverflows: true, child: child);\n                    }\n                    return AnnotatedRegion<SystemUiOverlayStyle>(\n                      value: SystemUiOverlayStyle(\n                        statusBarColor: theme.scaffoldBackgroundColor,\n                        systemNavigationBarColor: theme.scaffoldBackgroundColor,\n                        systemNavigationBarIconBrightness: theme.brightness == Brightness.dark\n                            ? Brightness.light\n                            : Brightness.dark,\n                      ),\n                      child: child,\n                    );\n                  },\n                );\n              },\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n\n  // @override\n  // Widget build1(BuildContext context, WidgetRef ref) {\n  //   setupStateListener(ref);\n  //   // setupQuickSettings(ref);\n  //   final router = ref.watch(routerProvider);\n  //   final locale = ref.watch(localePreferencesProvider);\n  //   final themeMode = ref.watch(themePreferencesProvider);\n  //   final theme = AppTheme(themeMode, locale.preferredFontFamily);\n  //   final upgrader = ref.watch(upgraderProvider);\n\n  //   ref.listen(foregroundProfilesUpdateNotifierProvider, (_, __) {});\n\n  //   return WindowWrapper(\n  //     TrayWrapper(\n  //       ShortcutWrapper(\n  //         ConnectionWrapper(\n  //           PlatformProvider(\n  //               settings: PlatformSettingsData(\n  //                 iosUsesMaterialWidgets: true,\n  //               ),\n  //               builder: (context) => DynamicColorBuilder(\n  //                     builder: (ColorScheme? lightColorScheme, ColorScheme? darkColorScheme) {\n  //                       return PlatformApp.router(\n  //                         routerConfig: router,\n  //                         locale: locale.flutterLocale,\n  //                         supportedLocales: AppLocaleUtils.supportedLocales,\n  //                         localizationsDelegates: GlobalMaterialLocalizations.delegates,\n  //                         debugShowCheckedModeBanner: false,\n  //                         material: (context, platform) => MaterialAppRouterData(\n  //                           theme: theme.lightTheme(lightColorScheme),\n  //                           darkTheme: theme.darkTheme(darkColorScheme),\n  //                           themeMode: themeMode.flutterThemeMode,\n  //                         ),\n  //                         cupertino: (context, platform) {\n  //                           final sysDark = MediaQuery.of(context).platformBrightness == Brightness.dark;\n\n  //                           return CupertinoAppRouterData(theme: theme.cupertinoThemeData(sysDark, lightColorScheme, darkColorScheme));\n  //                         },\n  //                         title: Constants.appName,\n  //                         builder: (context, child) {\n  //                           child = UpgradeAlert(\n  //                             upgrader: upgrader,\n  //                             navigatorKey: router.routerDelegate.navigatorKey,\n  //                             child: child ?? const SizedBox(),\n  //                           );\n  //                           if (kDebugMode && _debugAccessibility) {\n  //                             return AccessibilityTools(\n  //                               checkFontOverflows: true,\n  //                               child: child,\n  //                             );\n  //                           }\n  //                           return child;\n  //                         },\n  //                       );\n  //                     },\n  //                   )),\n  //         ),\n  //       ),\n  //     ),\n  //   );\n  // }\n\n  void setupStateListener(WidgetRef ref) {\n    final appLifecycleState = useAppLifecycleState();\n\n    useEffect(() {\n      loggy.info(\"current app state\");\n      loggy.info(appLifecycleState);\n      if (appLifecycleState == AppLifecycleState.paused) {\n        onPause(ref);\n      } else if (appLifecycleState == AppLifecycleState.inactive) {\n        onInactive(ref);\n      } else if (appLifecycleState == AppLifecycleState.resumed) {\n        onResume(ref);\n      }\n      return null;\n    }, [appLifecycleState]);\n  }\n}\n"
  },
  {
    "path": "lib/features/app_update/data/app_update_data_providers.dart",
    "content": "import 'package:hiddify/core/http_client/http_client_provider.dart';\nimport 'package:hiddify/features/app_update/data/app_update_repository.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'app_update_data_providers.g.dart';\n\n@Riverpod(keepAlive: true)\nAppUpdateRepository appUpdateRepository(AppUpdateRepositoryRef ref) {\n  return AppUpdateRepositoryImpl(httpClient: ref.watch(httpClientProvider));\n}\n"
  },
  {
    "path": "lib/features/app_update/data/app_update_repository.dart",
    "content": "import 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/http_client/dio_http_client.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/model/environment.dart';\nimport 'package:hiddify/core/utils/exception_handler.dart';\nimport 'package:hiddify/features/app_update/data/github_release_parser.dart';\nimport 'package:hiddify/features/app_update/model/app_update_failure.dart';\nimport 'package:hiddify/features/app_update/model/remote_version_entity.dart';\nimport 'package:hiddify/utils/utils.dart';\n\nabstract interface class AppUpdateRepository {\n  TaskEither<AppUpdateFailure, RemoteVersionEntity> getLatestVersion({\n    bool includePreReleases = false,\n    Release release = Release.general,\n  });\n}\n\nclass AppUpdateRepositoryImpl with ExceptionHandler, InfraLogger implements AppUpdateRepository {\n  AppUpdateRepositoryImpl({required this.httpClient});\n\n  final DioHttpClient httpClient;\n\n  @override\n  TaskEither<AppUpdateFailure, RemoteVersionEntity> getLatestVersion({\n    bool includePreReleases = false,\n    Release release = Release.general,\n  }) {\n    return exceptionHandler(() async {\n      if (!release.allowCustomUpdateChecker) {\n        throw Exception(\"custom update checkers are not supported\");\n      }\n      final response = await httpClient.get<List>(Constants.githubReleasesApiUrl);\n      if (response.statusCode != 200 || response.data == null) {\n        loggy.warning(\"failed to fetch latest version info\");\n        return left(const AppUpdateFailure.unexpected());\n      }\n\n      final releases = response.data!.map((e) => GithubReleaseParser.parse(e as Map<String, dynamic>));\n      late RemoteVersionEntity latest;\n      if (includePreReleases) {\n        latest = releases.first;\n      } else {\n        latest = releases.firstWhere((e) => e.preRelease == false);\n      }\n      return right(latest);\n    }, AppUpdateFailure.unexpected);\n  }\n}\n"
  },
  {
    "path": "lib/features/app_update/data/github_release_parser.dart",
    "content": "import 'package:dartx/dartx.dart';\nimport 'package:hiddify/core/model/environment.dart';\nimport 'package:hiddify/features/app_update/model/remote_version_entity.dart';\n\nabstract class GithubReleaseParser {\n  static RemoteVersionEntity parse(Map<String, dynamic> json) {\n    final fullTag = json['tag_name'] as String;\n    final fullVersion = fullTag.removePrefix(\"v\").split(\"-\").first.split(\"+\");\n    var version = fullVersion.first;\n    var buildNumber = fullVersion.elementAtOrElse(1, (index) => \"\");\n    var flavor = Environment.prod;\n    for (final env in Environment.values) {\n      final suffix = \".${env.name}\";\n      if (version.endsWith(suffix)) {\n        version = version.removeSuffix(suffix);\n        flavor = env;\n        break;\n      } else if (buildNumber.endsWith(suffix)) {\n        buildNumber = buildNumber.removeSuffix(suffix);\n        flavor = env;\n        break;\n      }\n    }\n    final preRelease = json[\"prerelease\"] as bool;\n    final publishedAt = DateTime.parse(json[\"published_at\"] as String);\n    return RemoteVersionEntity(\n      version: version,\n      buildNumber: buildNumber,\n      releaseTag: fullTag,\n      preRelease: preRelease,\n      url: json[\"html_url\"] as String,\n      publishedAt: publishedAt,\n      flavor: flavor,\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/app_update/model/app_update_failure.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\n\npart 'app_update_failure.freezed.dart';\n\n@freezed\nsealed class AppUpdateFailure with _$AppUpdateFailure, Failure {\n  const AppUpdateFailure._();\n\n  @With<UnexpectedFailure>()\n  const factory AppUpdateFailure.unexpected([Object? error, StackTrace? stackTrace]) = AppUpdateUnexpectedFailure;\n\n  @override\n  ({String type, String? message}) present(TranslationsEn t) {\n    return switch (this) {\n      AppUpdateUnexpectedFailure() => (type: t.errors.unexpected, message: null),\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/app_update/model/remote_version_entity.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/model/environment.dart';\n\npart 'remote_version_entity.freezed.dart';\n\n@Freezed()\nclass RemoteVersionEntity with _$RemoteVersionEntity {\n  const RemoteVersionEntity._();\n\n  const factory RemoteVersionEntity({\n    required String version,\n    required String buildNumber,\n    required String releaseTag,\n    required bool preRelease,\n    required String url,\n    required DateTime publishedAt,\n    required Environment flavor,\n  }) = _RemoteVersionEntity;\n\n  String get presentVersion => flavor == Environment.prod ? version : \"$version ${flavor.name}\";\n}\n"
  },
  {
    "path": "lib/features/app_update/notifier/app_update_notifier.dart",
    "content": "import 'package:flutter/foundation.dart';\nimport 'package:hiddify/core/app_info/app_info_provider.dart';\nimport 'package:hiddify/core/localization/locale_preferences.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/model/environment.dart';\nimport 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/core/utils/preferences_utils.dart';\nimport 'package:hiddify/features/app_update/data/app_update_data_providers.dart';\nimport 'package:hiddify/features/app_update/model/app_update_failure.dart';\nimport 'package:hiddify/features/app_update/model/remote_version_entity.dart';\nimport 'package:hiddify/features/app_update/notifier/app_update_state.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:upgrader/upgrader.dart';\nimport 'package:version/version.dart';\n\npart 'app_update_notifier.g.dart';\n\nconst _debugUpgrader = true;\n\n@riverpod\nUpgrader upgrader(Ref ref) => Upgrader(\n  storeController: UpgraderStoreController(\n    onAndroid: () => ref.read(appInfoProvider).requireValue.release.allowCustomUpdateChecker\n        ? UpgraderAppcastStore(appcastURL: Constants.appCastUrl)\n        : UpgraderPlayStore(),\n    oniOS: () => UpgraderAppStore(),\n    onLinux: () => UpgraderAppcastStore(appcastURL: Constants.appCastUrl),\n    onWindows: () => UpgraderAppcastStore(appcastURL: Constants.appCastUrl),\n    onMacOS: () => UpgraderAppcastStore(appcastURL: Constants.appCastUrl),\n    onWeb: () => UpgraderAppcastStore(appcastURL: Constants.appCastUrl),\n  ),\n  debugLogging: false && _debugUpgrader && kDebugMode,\n  // durationUntilAlertAgain: const Duration(hours: 12),\n  messages: UpgraderMessages(code: ref.watch(localePreferencesProvider).languageCode),\n);\n\n@Riverpod(keepAlive: true)\nclass AppUpdateNotifier extends _$AppUpdateNotifier with AppLogger {\n  @override\n  AppUpdateState build() => const AppUpdateState.initial();\n\n  PreferencesEntry<String?, dynamic> get _ignoreReleasePref => PreferencesEntry(\n    preferences: ref.read(sharedPreferencesProvider).requireValue,\n    key: 'ignored_release_version',\n    defaultValue: null,\n  );\n\n  Future<AppUpdateState> check() async {\n    loggy.debug(\"checking for update\");\n    state = const AppUpdateState.checking();\n    final appInfo = ref.watch(appInfoProvider).requireValue;\n    if (!appInfo.release.allowCustomUpdateChecker) {\n      loggy.debug(\"custom update checkers are not allowed for [${appInfo.release.name}] release\");\n      return state = const AppUpdateState.disabled();\n    }\n    return ref\n        .watch(appUpdateRepositoryProvider)\n        .getLatestVersion()\n        .match(\n          (err) {\n            loggy.warning(\"failed to get latest version\", err);\n            return state = AppUpdateState.error(err);\n          },\n          (remote) {\n            try {\n              final latestVersion = Version.parse(remote.version);\n              final currentVersion = Version.parse(appInfo.version);\n              if (latestVersion > currentVersion) {\n                if (remote.version == _ignoreReleasePref.read()) {\n                  loggy.debug(\"ignored release [${remote.version}]\");\n                  return state = AppUpdateStateIgnored(remote);\n                }\n                loggy.debug(\"new version available: $remote\");\n                return state = AppUpdateState.available(remote);\n              }\n              loggy.info(\"already using latest version[$currentVersion], remote: [${remote.version}]\");\n              return state = const AppUpdateState.notAvailable();\n            } catch (error, stackTrace) {\n              loggy.warning(\"error parsing versions\", error, stackTrace);\n              return state = AppUpdateState.error(AppUpdateFailure.unexpected(error, stackTrace));\n            }\n          },\n        )\n        .run();\n  }\n\n  Future<void> ignoreRelease(RemoteVersionEntity version) async {\n    loggy.debug(\"ignoring release [${version.version}]\");\n    await _ignoreReleasePref.write(version.version);\n    state = AppUpdateStateIgnored(version);\n  }\n}\n"
  },
  {
    "path": "lib/features/app_update/notifier/app_update_state.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/features/app_update/model/app_update_failure.dart';\nimport 'package:hiddify/features/app_update/model/remote_version_entity.dart';\n\npart 'app_update_state.freezed.dart';\n\n@freezed\nclass AppUpdateState with _$AppUpdateState {\n  const factory AppUpdateState.initial() = AppUpdateStateInitial;\n  const factory AppUpdateState.disabled() = AppUpdateStateDisabled;\n  const factory AppUpdateState.checking() = AppUpdateStateChecking;\n  const factory AppUpdateState.error(AppUpdateFailure error) = AppUpdateStateError;\n  const factory AppUpdateState.available(RemoteVersionEntity versionInfo) = AppUpdateStateAvailable;\n  const factory AppUpdateState.ignored(RemoteVersionEntity versionInfo) = AppUpdateStateIgnored;\n  const factory AppUpdateState.notAvailable() = AppUpdateStateNotAvailable;\n}\n"
  },
  {
    "path": "lib/features/auto_start/notifier/auto_start_notifier.dart",
    "content": "import 'dart:async';\nimport 'dart:io';\n\nimport 'package:hiddify/core/app_info/app_info_provider.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:launch_at_startup/launch_at_startup.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'auto_start_notifier.g.dart';\n\n@Riverpod(keepAlive: true)\nclass AutoStartNotifier extends _$AutoStartNotifier with InfraLogger {\n  Timer? _timer;\n\n  @override\n  Future<bool> build() async {\n    if (!PlatformUtils.isDesktop) return false;\n    final appInfo = ref.watch(appInfoProvider).requireValue;\n    launchAtStartup.setup(\n      appName: appInfo.name,\n      appPath: Platform.resolvedExecutable,\n      packageName: \"Hiddify.HiddifyNext\",\n    );\n    final isEnabled = await launchAtStartup.isEnabled();\n    loggy.info(\"auto start is [${isEnabled ? \"Enabled\" : \"Disabled\"}]\");\n    _startTimer();\n    ref.onDispose(() => _timer?.cancel());\n    return isEnabled;\n  }\n\n  void _startTimer() {\n    _timer?.cancel();\n    _timer = Timer.periodic(const Duration(minutes: 15), (timer) => updateStatus());\n  }\n\n  Future<bool> updateStatus() async {\n    loggy.debug(\"update auto start status\");\n    final isEnabled = await launchAtStartup.isEnabled();\n    state = AsyncValue.data(isEnabled);\n    return isEnabled;\n  }\n\n  Future<void> enable() async {\n    loggy.debug(\"enabling auto start\");\n    await launchAtStartup.enable();\n    state = const AsyncValue.data(true);\n  }\n\n  Future<void> disable() async {\n    loggy.debug(\"disabling auto start\");\n    await launchAtStartup.disable();\n    state = const AsyncValue.data(false);\n  }\n}\n"
  },
  {
    "path": "lib/features/common/custom_text_scroll.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:text_scroll/text_scroll.dart';\n\nclass CustomTextScroll extends ConsumerWidget {\n  const CustomTextScroll(this.text, {super.key, this.style});\n\n  final String text;\n  final TextStyle? style;\n\n  double calculateHeight(BuildContext context) {\n    final TextPainter textPainter = TextPainter(\n      text: TextSpan(text: text, style: style),\n      textDirection: Directionality.of(context),\n      maxLines: 1,\n      textScaler: MediaQuery.of(context).textScaler,\n    )..layout();\n    return textPainter.height;\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    return SizedBox(\n      height: calculateHeight(context),\n      child: TextScroll(\n        text,\n        mode: TextScrollMode.bouncing,\n        velocity: const Velocity(pixelsPerSecond: Offset(30, 0)),\n        pauseOnBounce: const Duration(seconds: 2),\n        pauseBetween: const Duration(seconds: 2),\n        style: style,\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/common/general_pref_tiles.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/analytics/analytics_controller.dart';\nimport 'package:hiddify/core/localization/locale_extensions.dart';\nimport 'package:hiddify/core/localization/locale_preferences.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/core/theme/app_theme_mode.dart';\nimport 'package:hiddify/core/theme/theme_preferences.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass LocalePrefTile extends ConsumerWidget {\n  const LocalePrefTile({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    final locale = ref.watch(localePreferencesProvider);\n    return ListTile(\n      title: Text(t.pages.settings.general.locale),\n      subtitle: Text(locale.localeName),\n      leading: const Icon(Icons.translate_rounded),\n      onTap: () async {\n        final selectedLocale = await ref\n            .read(dialogNotifierProvider.notifier)\n            .showSettingPicker<AppLocale>(\n              title: t.pages.settings.general.locale,\n              selected: locale,\n              onReset: () => ref.read(localePreferencesProvider.notifier).changeLocale(AppLocale.en),\n              options: AppLocale.values,\n              getTitle: (e) => e.localeName,\n            );\n        if (selectedLocale != null) {\n          await ref.read(localePreferencesProvider.notifier).changeLocale(selectedLocale);\n        }\n      },\n    );\n  }\n}\n\nclass EnableAnalyticsPrefTile extends ConsumerWidget {\n  const EnableAnalyticsPrefTile({super.key, this.onChanged});\n\n  final ValueChanged<bool>? onChanged;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    final enabled = ref.watch(analyticsControllerProvider).requireValue;\n\n    return SwitchListTile.adaptive(\n      title: Text(t.pages.settings.general.enableAnalytics),\n      subtitle: Text(t.pages.settings.general.enableAnalyticsMsg, style: Theme.of(context).textTheme.bodySmall),\n      secondary: const Icon(Icons.analytics_rounded),\n      value: enabled,\n      onChanged: (value) async {\n        if (onChanged != null) {\n          return onChanged!(value);\n        }\n        if (enabled) {\n          await ref.read(analyticsControllerProvider.notifier).disableAnalytics();\n        } else {\n          await ref.read(analyticsControllerProvider.notifier).enableAnalytics();\n        }\n      },\n    );\n  }\n}\n\nclass ThemeModePrefTile extends ConsumerWidget {\n  const ThemeModePrefTile({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    final themeMode = ref.watch(themePreferencesProvider);\n\n    return ListTile(\n      title: Text(t.pages.settings.general.themeMode),\n      subtitle: Text(themeMode.present(t)),\n      leading: Icon(switch (ref.watch(themePreferencesProvider)) {\n        AppThemeMode.system => Icons.auto_awesome_rounded,\n        AppThemeMode.light => Icons.light_mode_rounded,\n        AppThemeMode.dark => Icons.dark_mode_rounded,\n        AppThemeMode.black => Icons.contrast_rounded,\n      }),\n      onTap: () async {\n        final selectedThemeMode = await ref\n            .read(dialogNotifierProvider.notifier)\n            .showSettingPicker<AppThemeMode>(\n              title: t.pages.settings.general.themeMode,\n              selected: themeMode,\n              onReset: () => ref.read(themePreferencesProvider.notifier).changeThemeMode(AppThemeMode.system),\n              options: AppThemeMode.values,\n              getTitle: (e) => e.present(t),\n            );\n        if (selectedThemeMode != null) {\n          await ref.read(themePreferencesProvider.notifier).changeThemeMode(selectedThemeMode);\n        }\n      },\n    );\n  }\n}\n\nclass ClosingPrefTile extends ConsumerWidget {\n  const ClosingPrefTile({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    final action = ref.watch(Preferences.actionAtClose);\n\n    return ListTile(\n      title: Text(t.pages.settings.general.actionAtClosing),\n      subtitle: Text(action.present(t)),\n      leading: const Icon(Icons.logout_rounded),\n      onTap: () async {\n        final selectedAction = await ref.read(dialogNotifierProvider.notifier).showActionAtClosing(selected: action);\n        if (selectedAction != null) {\n          await ref.read(Preferences.actionAtClose.notifier).update(selectedAction);\n        }\n      },\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/common/qr_code_dialog.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:qr_flutter/qr_flutter.dart';\n\nclass QrCodeDialog extends StatelessWidget {\n  const QrCodeDialog(this.data, {super.key, this.message, this.width = 268, this.backgroundColor = Colors.white});\n\n  final String data;\n  final String? message;\n  final double width;\n  final Color backgroundColor;\n\n  @override\n  Widget build(BuildContext context) {\n    final theme = Theme.of(context);\n\n    return Padding(\n      padding: const EdgeInsets.all(8.0),\n      child: Column(\n        mainAxisAlignment: MainAxisAlignment.center,\n        children: [\n          SizedBox(\n            width: width,\n            child: QrImageView(data: data, backgroundColor: backgroundColor),\n          ),\n          if (message != null)\n            SizedBox(\n              width: width,\n              child: Material(\n                color: theme.colorScheme.surface,\n                child: Row(\n                  mainAxisAlignment: MainAxisAlignment.center,\n                  children: [\n                    Flexible(\n                      child: Text(\n                        message!,\n                        overflow: TextOverflow.ellipsis,\n                        style: TextStyle(color: theme.colorScheme.onSurface),\n                      ),\n                    ),\n                  ],\n                ),\n              ),\n            ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/common/qr_code_scanner_screen.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:mobile_scanner/mobile_scanner.dart';\n\n// // const permissions = [Permissions.CAMERA];\n// // const permissionGroup = [PermissionGroup.Camera];\n\n// class QRCodeScannerScreen extends StatefulHookConsumerWidget {\n//   const QRCodeScannerScreen({super.key});\n\n//   Future<String?> open(BuildContext context) async {\n//     return Navigator.of(context, rootNavigator: true).push(\n//       MaterialPageRoute(\n//         fullscreenDialog: true,\n//         builder: (context) => const QRCodeScannerScreen(),\n//       ),\n//     );\n//   }\n\n//   @override\n//   ConsumerState<QRCodeScannerScreen> createState() => _QRCodeScannerScreenState();\n// }\n\n// class _QRCodeScannerScreenState extends ConsumerState<QRCodeScannerScreen> with WidgetsBindingObserver, PresLogger {\n//   final MobileScannerController controller = MobileScannerController(\n//     detectionTimeoutMs: 500,\n//     autoStart: false,\n//   );\n//   bool started = false;\n\n//   // late FlutterEasyPermission _easyPermission;\n//   @override\n//   void initState() {\n//     super.initState();\n//     WidgetsBinding.instance.addObserver(this);\n//     // _initializeScanner();\n\n//     // _easyPermission = FlutterEasyPermission()\n//     //   ..addPermissionCallback(onGranted: (requestCode, androidPerms, iosPerm) {\n//     //     debugPrint(\"android:$androidPerms\");\n//     //     debugPrint(\"iOS:$iosPerm\");\n//     //     startQrScannerIfPermissionGranted();\n//     //   }, onDenied: (requestCode, androidPerms, iosPerm, isPermanent) {\n//     //     if (isPermanent) {\n//     //       FlutterEasyPermission.showAppSettingsDialog(title: \"Camera\");\n//     //     } else {\n//     //       debugPrint(\"android:$androidPerms\");\n//     //       debugPrint(\"iOS:$iosPerm\");\n//     //     }\n//     //   }, onSettingsReturned: () {\n//     //     startQrScannerIfPermissionGranted();\n//     //   });\n//   }\n\n// //   Future<bool> _requestCameraPermission() async {\n// //     final hasPermission = await FlutterEasyPermission.has(\n// //       perms: permissions,\n// //       permsGroup: permissionGroup,\n// //     );\n\n// //     if (hasPermission) return true;\n\n// //     final completer = Completer<bool>();\n\n// //     void permissionCallback(int requestCode, List<Permissions>? perms, PermissionGroup? perm) {\n// //       if (!completer.isCompleted) {\n// //         completer.complete(true);\n// //       }\n// //     }\n\n// //     void permissionDeniedCallback(int requestCode, List<Permissions>? perms, PermissionGroup? perm, bool isPermanent) {\n// //       if (!completer.isCompleted) {\n// //         completer.complete(false);\n// //       }\n// //     }\n\n// //     FlutterEasyPermission().addPermissionCallback(\n// //       onGranted: permissionCallback,\n// //       onDenied: permissionDeniedCallback,\n// //     );\n\n// //     FlutterEasyPermission.request(\n// //       perms: permissions,\n// //       permsGroup: permissionGroup,\n// //       rationale: \"Camera permission is required to scan QR codes.\",\n// //     );\n\n// //     return completer.future;\n// //   }\n\n// //   Future<void> _initializeScanner() async {\n// //     final hasPermission = await _requestCameraPermission();\n// //     if (hasPermission) {\n// //       _startScanner();\n// //     } else {\n// //       _showPermissionDialog();\n// //     }\n// //   }\n\n// //   @override\n// //   void dispose() {\n// //     controller.dispose();\n// //     // _easyPermission.dispose();\n// //     FlutterEasyPermission().dispose();\n// //     WidgetsBinding.instance.removeObserver(this);\n// //     super.dispose();\n// //   }\n\n// //   @override\n// //   void didChangeAppLifecycleState(AppLifecycleState state) {\n// //     /// Checking app cycle so that when user returns from settings, need to recheck for permissions\n// //     if (state == AppLifecycleState.resumed) {\n// //       _checkPermissionAndStartScanner();\n// //     }\n// //   }\n\n// //   Future<void> _checkPermissionAndStartScanner() async {\n// //     final hasPermission = await FlutterEasyPermission.has(\n// //       perms: permissions,\n// //       permsGroup: permissionGroup,\n// //     );\n// //     if (hasPermission) {\n// //       _startScanner();\n// //     } else {\n// //       setState(() {}); // Trigger rebuild to show permission denied UI\n// //     }\n// //   }\n\n// //   Future<void> _startScanner() async {\n// //     loggy.info(\"Starting scanner\");\n// //     await controller.stop();\n// //     await controller.start().whenComplete(() {\n// //       setState(() {\n// //         started = true;\n// //       });\n// //     }).catchError((error) {\n// //       loggy.warning(\"Error starting scanner: $error\");\n// //     });\n// //   }\n\n// //   Future<void> startQrScannerIfPermissionIsGranted() async {\n// //     final hasPermission = await FlutterEasyPermission.has(\n// //       perms: permissions,\n// //       permsGroup: permissionGroup,\n// //     );\n// //     if (hasPermission) {\n// //       _startScanner();\n// //       // } else {\n// //       //   _showPermissionDialog();\n// //     }\n// //   }\n\n// //   // void startQrScannerIfPermissionGranted() {\n// //   //   FlutterEasyPermission.has(perms: permissions, permsGroup: permissionGroup).then((value) {\n// //   //     if (value) {\n// //   //       controller.start().then((result) {\n// //   //         if (result != null) {\n// //   //           setState(() {\n// //   //             started = true;\n// //   //           });\n// //   //         }\n// //   //       }).catchError((error) {\n// //   //         loggy.warning(\"Error starting scanner: $error\");\n// //   //       });\n// //   //     } else {}\n// //   //   });\n// //   // }\n\n// //   void _showPermissionDialog() {\n// //     FlutterEasyPermission.showAppSettingsDialog(\n// //       title: \"Camera Access Required\",\n// //       rationale: \"Permission to camera to scan QR Code\",\n// //       positiveButtonText: \"Settings\",\n// //       negativeButtonText: \"Cancel\",\n// //     );\n// //   }\n\n//   @override\n//   Widget build(BuildContext context) {\n//     final Translations t = ref.watch(translationsProvider).requireValue;\n//     // return FutureBuilder(\n//     //   future: FlutterEasyPermission.has(\n//     //     perms: permissions,\n//     //     permsGroup: permissionGroup,\n//     //   ),\n//     //   builder: (context, snapshot) {\n//     //     if (snapshot.connectionState == ConnectionState.waiting) {\n//     //       return const Center(child: CircularProgressIndicator());\n//     //     }\n\n//     //     if (snapshot.data == true) {\n//     //       return _buildScannerUI(context, t);\n//     //     } else {\n//     //       return _buildPermissionDeniedUI(context, t);\n//     //     }\n//     //   },\n//     // );\n//     return MobileScanner(\n//       overlayBuilder: (context, constraints) => ScannerOverlay(),\n//       onDetect: (barcodes) {\n//         final rawData = barcodes.barcodes.first.rawValue;\n//         loggy.debug('captured raw: [$rawData]');\n//         if (rawData != null) {\n//           final uri = Uri.tryParse(rawData);\n//           if (context.mounted && uri != null) {\n//             loggy.debug('captured url: [$uri]');\n//             Navigator.of(context, rootNavigator: true).pop(uri.toString());\n//           }\n//         } else {\n//           loggy.warning(\"unable to capture\");\n//         }\n//       },\n//     );\n//     return _buildScannerUI(context, t);\n//   }\n\n//   Widget _buildScannerUI(BuildContext context, Translations t) {\n//     final size = MediaQuery.sizeOf(context);\n//     final overlaySize = (size.shortestSide - 12).coerceAtMost(248);\n//     // _startScanner();\n//     return Scaffold(\n//       extendBodyBehindAppBar: true,\n//       appBar: AppBar(\n//         backgroundColor: Colors.transparent,\n//         iconTheme: Theme.of(context).iconTheme.copyWith(\n//               color: Colors.white,\n//               size: 32,\n//             ),\n//         actions: [\n//           IconButton(\n//             icon: const Icon(FluentIcons.flash_24_regular),\n//             tooltip: t.profile.add.qrScanner.torchSemanticLabel,\n//             onPressed: () => controller.toggleTorch(),\n//           ),\n//           // IconButton(\n//           //   icon: ValueListenableBuilder(\n//           //     valueListenable: controller.torchState,\n//           //     builder: (context, state, child) {\n//           //       switch (state) {\n//           //         case TorchState.off:\n//           //           return const Icon(\n//           //             FluentIcons.flash_off_24_regular,\n//           //             color: Colors.grey,\n//           //           );\n//           //         case TorchState.on:\n//           //           return const Icon(\n//           //             FluentIcons.flash_24_regular,\n//           //             color: Colors.yellow,\n//           //           );\n//           //       }\n//           //     },\n//           //   ),\n//           //   tooltip: t.profile.add.qrScanner.torchSemanticLabel,\n//           //   onPressed: () => controller.toggleTorch(),\n//           // ),\n//           IconButton(\n//             icon: const Icon(FluentIcons.camera_switch_24_regular),\n//             tooltip: t.profile.add.qrScanner.facingSemanticLabel,\n//             onPressed: () => controller.switchCamera(),\n//           ),\n//         ],\n//       ),\n//       body: Stack(\n//         children: [\n//           MobileScanner(\n//             controller: controller,\n//             onDetect: (capture) {\n//               final rawData = capture.barcodes.first.rawValue;\n//               loggy.debug('captured raw: [$rawData]');\n//               if (rawData != null) {\n//                 final uri = Uri.tryParse(rawData);\n//                 if (context.mounted && uri != null) {\n//                   loggy.debug('captured url: [$uri]');\n//                   Navigator.of(context, rootNavigator: true).pop(uri.toString());\n//                 }\n//               } else {\n//                 loggy.warning(\"unable to capture\");\n//               }\n//             },\n//             errorBuilder: (_, error, __) {\n//               final message = switch (error.errorCode) {\n//                 MobileScannerErrorCode.permissionDenied => t.profile.add.qrScanner.permissionDeniedError,\n//                 _ => t.profile.add.qrScanner.unexpectedError,\n//               };\n\n//               return Center(\n//                 child: Column(\n//                   mainAxisSize: MainAxisSize.min,\n//                   children: [\n//                     const Padding(\n//                       padding: EdgeInsets.only(bottom: 8),\n//                       child: Icon(\n//                         FluentIcons.error_circle_24_regular,\n//                         color: Colors.white,\n//                       ),\n//                     ),\n//                     Text(message),\n//                     Text(error.errorDetails?.message ?? ''),\n//                   ],\n//                 ),\n//               );\n//             },\n//           ),\n//           if (started)\n//             CustomPaint(\n//               painter: ScannerOverlay(\n//                 Rect.fromCenter(\n//                   center: size.center(Offset.zero),\n//                   width: overlaySize,\n//                   height: overlaySize,\n//                 ),\n//               ),\n//             ),\n//         ],\n//       ),\n//     );\n//   }\n\n//   Widget _buildPermissionDeniedUI(BuildContext context, Translations t) {\n//     return Scaffold(\n//       appBar: AppBar(\n//         backgroundColor: Colors.transparent,\n//         iconTheme: Theme.of(context).iconTheme.copyWith(\n//               color: Colors.white,\n//               size: 32,\n//             ),\n//       ),\n//       body: Center(\n//         child: Column(\n//           mainAxisAlignment: MainAxisAlignment.center,\n//           children: [\n//             Text(t.profile.add.qrScanner.permissionDeniedError),\n//             const SizedBox(height: 16),\n//             ElevatedButton(\n//               // onPressed: _showPermissionDialog,\n//               onPressed: () {},\n//               child: const Text(\"Settings\"),\n//             ),\n//           ],\n//         ),\n//       ),\n//     );\n//   }\n// }\n\n// class ScannerOverlay extends CustomPainter {\n//   ScannerOverlay(this.scanWindow);\n\n//   final Rect scanWindow;\n//   final double borderRadius = 12.0;\n\n//   @override\n//   void paint(Canvas canvas, Size size) {\n//     final backgroundPath = Path()..addRect(Rect.largest);\n//     final cutoutPath = Path()\n//       ..addRRect(\n//         RRect.fromRectAndCorners(\n//           scanWindow,\n//           topLeft: Radius.circular(borderRadius),\n//           topRight: Radius.circular(borderRadius),\n//           bottomLeft: Radius.circular(borderRadius),\n//           bottomRight: Radius.circular(borderRadius),\n//         ),\n//       );\n\n//     final backgroundPaint = Paint()\n//       ..color = Colors.black.withValues(alpha: .5)\n//       ..style = PaintingStyle.fill\n//       ..blendMode = BlendMode.dstOut;\n\n//     final backgroundWithCutout = Path.combine(\n//       PathOperation.difference,\n//       backgroundPath,\n//       cutoutPath,\n//     );\n\n//     final borderPaint = Paint()\n//       ..color = Colors.white\n//       ..style = PaintingStyle.stroke\n//       ..strokeWidth = 3.0;\n\n//     final borderRect = RRect.fromRectAndCorners(\n//       scanWindow,\n//       topLeft: Radius.circular(borderRadius),\n//       topRight: Radius.circular(borderRadius),\n//       bottomLeft: Radius.circular(borderRadius),\n//       bottomRight: Radius.circular(borderRadius),\n//     );\n\n//     canvas.drawPath(backgroundWithCutout, backgroundPaint);\n//     canvas.drawRRect(borderRect, borderPaint);\n//   }\n\n//   @override\n//   bool shouldRepaint(covariant CustomPainter oldDelegate) {\n//     return false;\n//   }\n// }\n\nclass QrCodeScannerDialog extends ConsumerWidget {\n  const QrCodeScannerDialog({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.read(translationsProvider).requireValue;\n    return Scaffold(\n      body: SafeArea(\n        child: Stack(\n          alignment: Alignment.center,\n          children: [\n            MobileScanner(\n              placeholderBuilder: (context) => const Center(child: CircularProgressIndicator()),\n              overlayBuilder: (context, constraints) => Container(\n                width: MediaQuery.of(context).size.width * 0.7,\n                height: MediaQuery.of(context).size.width * 0.7,\n                decoration: BoxDecoration(\n                  borderRadius: BorderRadius.circular(16),\n                  border: Border.all(color: Theme.of(context).colorScheme.primaryContainer, width: 4),\n                ),\n              ),\n              errorBuilder: (context, error) => Center(child: Text(t.common.msg.permission.denied)),\n              onDetect: (barcodes) {\n                final rawData = barcodes.barcodes.first.rawValue;\n                if (rawData != null) context.pop(rawData);\n                // loggy.debug('captured raw: [$rawData]');\n                // if (rawData != null) {\n                //   context.pop(rawData);\n                //   final uri = Uri.tryParse(rawData);\n                //   if (context.mounted && uri != null) {\n                //     // loggy.debug('captured url: [$uri]');\n                //     context.pop(uri.toString());\n                //   }\n                // } else {\n                //   // loggy.warning(\"unable to capture\");\n                // }\n              },\n            ),\n            Align(\n              alignment: AlignmentDirectional.topStart,\n              child: Container(\n                decoration: BoxDecoration(\n                  color: Theme.of(context).colorScheme.primaryContainer,\n                  borderRadius: BorderRadius.circular(1000),\n                ),\n                margin: const EdgeInsets.all(8),\n                child: IconButton(\n                  onPressed: () => context.pop(),\n                  icon: Icon(Icons.close, color: Theme.of(context).colorScheme.onPrimaryContainer),\n                  splashRadius: 24,\n                ),\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/connection/data/connection_data_providers.dart",
    "content": "import 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/features/connection/data/connection_repository.dart';\nimport 'package:hiddify/features/profile/data/profile_data_providers.dart';\nimport 'package:hiddify/features/settings/data/config_option_data_providers.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service_provider.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'connection_data_providers.g.dart';\n\n@Riverpod(keepAlive: true)\nConnectionRepository connectionRepository(Ref ref) {\n  return ConnectionRepositoryImpl(\n    ref: ref,\n    directories: ref.watch(appDirectoriesProvider).requireValue,\n    configOptionRepository: ref.watch(configOptionRepositoryProvider),\n    singbox: ref.watch(hiddifyCoreServiceProvider),\n    profilePathResolver: ref.watch(profilePathResolverProvider),\n  );\n}\n"
  },
  {
    "path": "lib/features/connection/data/connection_repository.dart",
    "content": "import 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/model/directories.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/core/utils/exception_handler.dart';\nimport 'package:hiddify/features/connection/model/connection_failure.dart';\nimport 'package:hiddify/features/connection/model/connection_status.dart';\nimport 'package:hiddify/features/profile/data/profile_path_resolver.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/notifier/warp_option/warp_option_notifier.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service.dart';\nimport 'package:hiddify/singbox/model/singbox_config_option.dart';\nimport 'package:hiddify/singbox/model/core_status.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:meta/meta.dart';\n\nabstract interface class ConnectionRepository {\n  SingboxConfigOption? get configOptionsSnapshot;\n\n  TaskEither<ConnectionFailure, Unit> setup();\n  Stream<ConnectionStatus> watchConnectionStatus();\n  TaskEither<ConnectionFailure, Unit> connect(ProfileEntity activeProfile, bool disableMemoryLimit);\n  TaskEither<ConnectionFailure, Unit> disconnect();\n  TaskEither<ConnectionFailure, Unit> reconnect(ProfileEntity activeProfile, bool disableMemoryLimit);\n}\n\nclass ConnectionRepositoryImpl with ExceptionHandler, InfraLogger implements ConnectionRepository {\n  ConnectionRepositoryImpl({\n    required this.ref,\n    required this.directories,\n    required this.singbox,\n    required this.configOptionRepository,\n    required this.profilePathResolver,\n  });\n\n  final Ref ref;\n\n  final Directories directories;\n  final HiddifyCoreService singbox;\n\n  final ConfigOptionRepository configOptionRepository;\n  final ProfilePathResolver profilePathResolver;\n\n  SingboxConfigOption? _configOptionsSnapshot;\n  @override\n  SingboxConfigOption? get configOptionsSnapshot => _configOptionsSnapshot;\n\n  bool _initialized = false;\n\n  @override\n  TaskEither<ConnectionFailure, Unit> setup() {\n    if (_initialized) return TaskEither.of(unit);\n    return exceptionHandler(() {\n      loggy.debug(\"setting up singbox\");\n\n      return singbox\n          .setup()\n          .map((r) {\n            _initialized = true;\n            return r;\n          })\n          .mapLeft(UnexpectedConnectionFailure.new)\n          .run();\n    }, UnexpectedConnectionFailure.new);\n  }\n\n  @override\n  Stream<ConnectionStatus> watchConnectionStatus() {\n    return singbox.watchStatus().map(\n      (event) => switch (event) {\n        CoreStopped() => Disconnected(event.getCoreAlert()),\n        CoreStarting() => const Connecting(),\n        CoreStarted() => const Connected(),\n        CoreStopping() => const Disconnecting(),\n      },\n    );\n  }\n\n  @override\n  TaskEither<ConnectionFailure, Unit> connect(ProfileEntity activeProfile, bool disableMemoryLimit) => setup().flatMap(\n    (_) => applyConfigOption(activeProfile).flatMap(\n      (_) => singbox.start(profilePathResolver.file(activeProfile.id).path, activeProfile.name, disableMemoryLimit),\n      // .mapLeft(UnexpectedConnectionFailure.new),\n    ),\n  );\n\n  @override\n  TaskEither<ConnectionFailure, Unit> disconnect() => singbox.stop().mapLeft(UnexpectedConnectionFailure.new);\n\n  @override\n  TaskEither<ConnectionFailure, Unit> reconnect(ProfileEntity activeProfile, bool disableMemoryLimit) =>\n      applyConfigOption(activeProfile).flatMap(\n        (_) => singbox\n            .restart(profilePathResolver.file(activeProfile.id).path, activeProfile.name, disableMemoryLimit)\n            .mapLeft(UnexpectedConnectionFailure.new),\n      );\n\n  @visibleForTesting\n  TaskEither<ConnectionFailure, Unit> applyConfigOption(ProfileEntity prof) =>\n      TaskEither.fromEither(configOptionRepository.fullOptionsOverrided(prof.profileOverride))\n          .mapLeft((l) => ConnectionFailure.invalidConfigOption(null, l))\n          .flatMap(\n            (overridedOptions) => TaskEither.tryCatch(() async {\n              final isWarpLicenseAgreed = ref.read(warpLicenseNotifierProvider);\n              final isWarpEnabled = overridedOptions.warp.enable || overridedOptions.warp2.enable;\n              if (!isWarpLicenseAgreed && isWarpEnabled) {\n                final isAgreed = await ref.read(dialogNotifierProvider.notifier).showWarpLicense();\n                if (isAgreed == true) {\n                  await ref.read(warpLicenseNotifierProvider.notifier).agree();\n                  // return (await applyConfigOption(prof).run()).match((l) => throw l, (_) => unit);\n                } else {\n                  throw const MissingWarpLicense();\n                }\n              }\n              _configOptionsSnapshot = overridedOptions;\n              await singbox.changeOptions(overridedOptions).run();\n              return unit;\n            }, (err, st) => err is ConnectionFailure ? err : ConnectionFailure.unexpected(err, st)),\n          );\n}\n"
  },
  {
    "path": "lib/features/connection/model/connection_failure.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/features/settings/model/config_option_failure.dart';\n\npart 'connection_failure.freezed.dart';\n\n@freezed\nsealed class ConnectionFailure with _$ConnectionFailure, Failure {\n  const ConnectionFailure._();\n\n  @With<UnexpectedFailure>()\n  const factory ConnectionFailure.unexpected([Object? error, StackTrace? stackTrace]) = UnexpectedConnectionFailure;\n\n  @With<ExpectedMeasuredFailure>()\n  const factory ConnectionFailure.missingVpnPermission([String? message]) = MissingVpnPermission;\n\n  @With<ExpectedMeasuredFailure>()\n  const factory ConnectionFailure.missingNotificationPermission([String? message]) = MissingNotificationPermission;\n\n  @With<ExpectedMeasuredFailure>()\n  const factory ConnectionFailure.missingPrivilege() = MissingPrivilege;\n\n  @With<ExpectedMeasuredFailure>()\n  const factory ConnectionFailure.invalidConfigOption([String? message, ConfigOptionFailure? configOptionFailure]) =\n      InvalidConfigOption;\n\n  @With<ExpectedMeasuredFailure>()\n  const factory ConnectionFailure.invalidConfig([String? message]) = InvalidConfig;\n\n  @With<ExpectedMeasuredFailure>()\n  const factory ConnectionFailure.backgroundCoreNotAvailable([String? message]) = BackgroundCoreNotAvailable;\n\n  @With<ExpectedMeasuredFailure>()\n  const factory ConnectionFailure.missiingWarpLicense() = MissingWarpLicense;\n\n  @override\n  ({String type, String? message}) present(TranslationsEn t) {\n    return switch (this) {\n      UnexpectedConnectionFailure(:final error) when error != null => (\n        type: t.errors.connectivity.unexpected,\n        message: \"$error\",\n      ),\n      UnexpectedConnectionFailure() => (type: t.errors.connectivity.unexpected, message: null),\n      MissingVpnPermission(:final message) => (type: t.errors.connectivity.missingVpnPermission, message: message),\n      MissingNotificationPermission(:final message) => (\n        type: t.errors.connectivity.missingNotificationPermission,\n        message: message,\n      ),\n      MissingPrivilege() => (type: t.errors.singbox.missingPrivilege, message: t.errors.singbox.missingPrivilegeMsg),\n      InvalidConfigOption(:final message, :final configOptionFailure) =>\n        configOptionFailure?.present(t) ?? (type: t.errors.singbox.invalidConfigOptions, message: message),\n      InvalidConfig(:final message) => (type: t.errors.singbox.invalidConfig, message: message),\n      BackgroundCoreNotAvailable(:final message) => (type: t.errors.connectivity.core, message: message),\n      MissingWarpLicense() => (type: t.errors.warp.missingLicense, message: t.errors.warp.missingLicenseMsg),\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/connection/model/connection_status.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/features/connection/model/connection_failure.dart';\n\npart 'connection_status.freezed.dart';\n\n@freezed\nsealed class ConnectionStatus with _$ConnectionStatus {\n  const ConnectionStatus._();\n\n  const factory ConnectionStatus.disconnected([ConnectionFailure? connectionFailure]) = Disconnected;\n  const factory ConnectionStatus.connecting() = Connecting;\n  const factory ConnectionStatus.connected() = Connected;\n  const factory ConnectionStatus.disconnecting() = Disconnecting;\n\n  bool get isConnected => switch (this) {\n    Connected() => true,\n    _ => false,\n  };\n\n  bool get isDisconnected => switch (this) {\n    Disconnected() => true,\n    _ => false,\n  };\n\n  bool get isSwitching => switch (this) {\n    Connecting() => true,\n    Disconnecting() => true,\n    _ => false,\n  };\n\n  String format() => switch (this) {\n    Disconnected(:final connectionFailure) =>\n      connectionFailure != null ? \"CONNECTION FAILURE: $connectionFailure\" : \"DISCONNECTED\",\n    Connecting() => \"CONNECTING\",\n    Connected() => \"CONNECTED\",\n    Disconnecting() => \"DISCONNECTING\",\n  };\n\n  String present(TranslationsEn t) => switch (this) {\n    Disconnected() => t.connection.tapToConnect,\n    Connecting() => t.connection.connecting,\n    Connected() => t.connection.connected,\n    Disconnecting() => t.connection.disconnecting,\n  };\n}\n"
  },
  {
    "path": "lib/features/connection/notifier/connection_notifier.dart",
    "content": "import 'dart:io';\n\nimport 'package:hiddify/core/haptic/haptic_service.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/connection/data/connection_data_providers.dart';\nimport 'package:hiddify/features/connection/data/connection_repository.dart';\nimport 'package:hiddify/features/connection/model/connection_failure.dart';\nimport 'package:hiddify/features/connection/model/connection_status.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/features/profile/notifier/active_profile_notifier.dart';\nimport 'package:hiddify/hiddifycore/init_signal.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:in_app_review/in_app_review.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:rxdart/rxdart.dart';\nimport 'package:sentry_flutter/sentry_flutter.dart';\n\npart 'connection_notifier.g.dart';\n\n@Riverpod(keepAlive: true)\nclass ConnectionNotifier extends _$ConnectionNotifier with AppLogger {\n  @override\n  Stream<ConnectionStatus> build() async* {\n    if (Platform.isIOS) {\n      await _connectionRepo.setup().mapLeft((l) {\n        loggy.error(\"error setting up connection repository\", l);\n      }).run();\n    }\n\n    listenSelf((previous, next) async {\n      if (previous == next) return;\n      if (previous case AsyncData(:final value) when !value.isConnected) {\n        if (next case AsyncData(value: final Connected _)) {\n          await ref.read(hapticServiceProvider.notifier).heavyImpact();\n\n          if (Platform.isAndroid && !ref.read(Preferences.storeReviewedByUser)) {\n            if (await InAppReview.instance.isAvailable()) {\n              InAppReview.instance.requestReview();\n              ref.read(Preferences.storeReviewedByUser.notifier).update(true);\n            }\n          }\n        }\n      }\n    });\n\n    ref.listen(activeProfileProvider.select((value) => value.asData?.value), (previous, next) async {\n      if (previous == null) return;\n      final shouldReconnect = next == null || previous.id != next.id;\n      if (shouldReconnect) {\n        await reconnect(next);\n      }\n    });\n    ref.watch(coreRestartSignalProvider);\n\n    yield* _connectionRepo.watchConnectionStatus().doOnData((event) {\n      if (event case Disconnected(connectionFailure: final _?) when PlatformUtils.isDesktop) {\n        ref.read(Preferences.startedByUser.notifier).update(false);\n      }\n      loggy.info(\"connection status: ${event.format()}\");\n    });\n  }\n\n  ConnectionRepository get _connectionRepo => ref.read(connectionRepositoryProvider);\n\n  Future<void> mayConnect() async {\n    if (state case AsyncData(:final value)) {\n      if (value case Disconnected()) return _connect();\n    }\n  }\n\n  Future<void> toggleConnection() async {\n    final haptic = ref.read(hapticServiceProvider.notifier);\n    if (state case AsyncError()) {\n      await haptic.lightImpact();\n      await _connect();\n    } else if (state case AsyncData(:final value)) {\n      switch (value) {\n        case Disconnected():\n          await haptic.lightImpact();\n          await ref.read(Preferences.startedByUser.notifier).update(true);\n          await _connect();\n        case Connected():\n          // default:\n          await haptic.mediumImpact();\n          await ref.read(Preferences.startedByUser.notifier).update(false);\n          await _disconnect();\n        default:\n          loggy.warning(\"switching status, debounce\");\n      }\n    }\n  }\n\n  Future<void> reconnect(ProfileEntity? profile) async {\n    if (state case AsyncData(:final value) when value == const Connected()) {\n      if (profile == null) {\n        loggy.info(\"no active profile, disconnecting\");\n        return _disconnect();\n      }\n      loggy.info(\"active profile changed, reconnecting\");\n      await ref.read(Preferences.startedByUser.notifier).update(true);\n      await _connectionRepo.reconnect(profile, ref.read(Preferences.disableMemoryLimit)).mapLeft((err) async {\n        loggy.warning(\"error reconnecting\", err);\n        state = AsyncError(err, StackTrace.current);\n        await ref\n            .read(dialogNotifierProvider.notifier)\n            .showCustomAlertFromErr(err.present(ref.read(translationsProvider).requireValue));\n      }).run();\n    }\n  }\n\n  Future<void> abortConnection() async {\n    if (state case AsyncData(:final value)) {\n      switch (value) {\n        case Connected() || Connecting():\n          loggy.debug(\"aborting connection\");\n          await _disconnect();\n        default:\n      }\n    }\n  }\n\n  final _singleStart = SingleCall();\n\n  Future<void> _connect() async {\n    _singleStart.run(\n      () async {\n        await _connectThrottled();\n      },\n      onIgnored: () {\n        loggy.debug(\"connect called while another connect/disconnect is still running, ignoring\");\n      },\n    );\n  }\n\n  Future<void> _connectThrottled() async {\n    final activeProfile = await ref.read(activeProfileProvider.future);\n    if (activeProfile == null) {\n      loggy.info(\"no active profile, not connecting\");\n      return;\n    }\n    await _connectionRepo.connect(activeProfile, ref.read(Preferences.disableMemoryLimit)).mapLeft((\n      ConnectionFailure err,\n    ) async {\n      loggy.warning(\"error connecting\", err);\n      //Go err is not normal object to see the go errors are string and need to be dumped\n      await ref\n          .read(dialogNotifierProvider.notifier)\n          .showCustomAlertFromErr(err.present(ref.read(translationsProvider).requireValue));\n      loggy.warning(err);\n      if (err.toString().contains(\"panic\")) {\n        await Sentry.captureException(Exception(err.toString()));\n      }\n      await ref.read(Preferences.startedByUser.notifier).update(false);\n      state = AsyncError(err, StackTrace.current);\n    }).run();\n  }\n\n  Future<void> _disconnect() async {\n    await _connectionRepo.disconnect().mapLeft((err) {\n      loggy.warning(\"error disconnecting\", err);\n      ref\n          .read(dialogNotifierProvider.notifier)\n          .showCustomAlertFromErr(err.present(ref.read(translationsProvider).requireValue));\n      state = AsyncError(err, StackTrace.current);\n    }).run();\n  }\n}\n\n@Riverpod(keepAlive: true)\nFuture<bool> serviceRunning(Ref ref) async {\n  // ref.watch(coreRestartSignalProvider);\n  return await ref\n      .watch(connectionNotifierProvider.selectAsync((data) => data.isConnected))\n      .onError((error, stackTrace) => false);\n}\n\nclass SingleCall {\n  bool _running = false;\n\n  Future<T> run<T>(Future<T> Function() task, {required T onIgnored}) async {\n    if (_running) return onIgnored;\n\n    _running = true;\n    try {\n      return await task();\n    } finally {\n      _running = false;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/features/connection/widget/connection_wrapper.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/features/profile/notifier/active_profile_notifier.dart';\nimport 'package:hiddify/features/settings/notifier/config_option/config_option_notifier.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ConnectionWrapper extends StatefulHookConsumerWidget {\n  const ConnectionWrapper(this.child, {super.key});\n\n  final Widget child;\n\n  @override\n  ConsumerState<ConsumerStatefulWidget> createState() => _ConnectionWrapperState();\n}\n\nclass _ConnectionWrapperState extends ConsumerState<ConnectionWrapper> with AppLogger {\n  @override\n  Widget build(BuildContext context) {\n    ref.listen(connectionNotifierProvider, (_, _) {});\n\n    ref.listen(configOptionNotifierProvider, (previous, next) async {\n      if (next case AsyncData(value: true)) {\n        final t = ref.read(translationsProvider).requireValue;\n        ref\n            .read(inAppNotificationControllerProvider)\n            .showInfoToast(\n              t.connection.reconnectMsg,\n              // actionText: t.connection.reconnect,\n              // callback: () async {\n              //   await ref\n              //       .read(connectionNotifierProvider.notifier)\n              //       .reconnect(await ref.read(activeProfileProvider.future));\n              // },\n            );\n        await ref.read(connectionNotifierProvider.notifier).reconnect(await ref.read(activeProfileProvider.future));\n      }\n    });\n\n    return widget.child;\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    // remove for now...\n    //\n    // Future.delayed(const Duration(seconds: 2)).then(\n    //   (_) async {\n    //     if (ref.read(startedByUserProvider) && PlatformUtils.isDesktop) {\n    //       loggy.debug(\"previously started by user, trying to connect\");\n    //       return ref.read(connectionNotifierProvider.notifier).mayConnect();\n    //     }\n    //   },\n    // );\n  }\n}\n"
  },
  {
    "path": "lib/features/deep_link/notifier/deep_link_notifier.dart",
    "content": "// part 'deep_link_notifier.g.dart';\n\n// typedef NewProfileLink = ({String? url, String? name});\n\n// @Riverpod(keepAlive: true)\n// class DeepLinkNotifier extends _$DeepLinkNotifier\n//     with ProtocolListener, InfraLogger {\n//   @override\n//   Future<NewProfileLink?> build() async {\n//     if (Platform.isLinux) return null;\n\n//     for (final protocol in LinkParser.protocols) {\n//       await protocolHandler.register(protocol);\n//     }\n//     protocolHandler.addListener(this);\n//     ref.onDispose(() {\n//       protocolHandler.removeListener(this);\n//     });\n\n//     final initialPayload = await protocolHandler.getInitialUrl();\n//     if (initialPayload != null) {\n//       loggy.debug('initial payload: [$initialPayload]');\n//       final link = LinkParser.deep(initialPayload);\n//       return link;\n//     }\n//     return null;\n//   }\n\n//   @override\n//   void onProtocolUrlReceived(String url) {\n//     super.onProtocolUrlReceived(url);\n//     loggy.debug(\"url received: [$url]\");\n//     final link = LinkParser.deep(url);\n//     if (link == null) {\n//       loggy.debug(\"link was not valid\");\n//       return;\n//     }\n//     update((_) => link);\n//   }\n// }\n"
  },
  {
    "path": "lib/features/home/widget/connection_button.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter_animate/flutter_animate.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/core/router/bottom_sheets/bottom_sheets_notifier.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/core/router/dialog/widgets/custom_alert_dialog.dart';\nimport 'package:hiddify/core/theme/theme_extensions.dart';\nimport 'package:hiddify/core/widget/animated_text.dart';\nimport 'package:hiddify/features/connection/model/connection_status.dart';\nimport 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/features/profile/notifier/active_profile_notifier.dart';\nimport 'package:hiddify/features/proxy/active/active_proxy_notifier.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/notifier/config_option/config_option_notifier.dart';\nimport 'package:hiddify/gen/assets.gen.dart';\nimport 'package:hiddify/singbox/model/singbox_config_enum.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\n// TODO: rewrite\nclass ConnectionButton extends HookConsumerWidget {\n  const ConnectionButton({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final connectionStatus = ref.watch(connectionNotifierProvider);\n    final activeProxy = ref.watch(activeProxyNotifierProvider);\n    final delay = activeProxy.valueOrNull?.urlTestDelay ?? 0;\n\n    final requiresReconnect = ref.watch(configOptionNotifierProvider).valueOrNull;\n    final today = DateTime.now();\n    // final animationController = useAnimationController(\n    //   duration: const Duration(seconds: 1),\n    // )..repeat(reverse: true); // Ensure the animation loops indefinitely\n\n    //   // Listen to the animation's value\n    //   final animationValue = useAnimation(Tween<double>(begin: 0.8, end: 1).animate(animationController));\n\n    //   // useEffect(() {\n    //   //   if (true) {\n    //   // Start repeating animation\n    //   //   } else {\n    //   //     animationController.stop(); // Stop animation if connected, disconnected, or error\n    //   //   }\n\n    //   //   // Cleanup when widget is disposed\n    //   //   return animationController.dispose;\n    //   // }, [connectionStatus.value]);\n\n    //   // ref.listen(\n    //   //   connectionNotifierProvider,\n    //   //   (_, next) {\n    //   //     if (next case AsyncError(:final error)) {\n    //   //       CustomAlertDialog.fromErr(t.presentError(error)).show(context);\n    //   //     }\n    //   //     if (next case AsyncData(value: Disconnected(:final connectionFailure?))) {\n    //   //       CustomAlertDialog.fromErr(t.presentError(connectionFailure)).show(context);\n    //   //     }\n    //   //   },\n    //   // );\n\n    const buttonTheme = ConnectionButtonTheme.light;\n\n    //   // return CircleDesignWidget(\n    //   //   onTap: switch (connectionStatus) {\n    //   //     // AsyncData(value: Disconnected()) || AsyncError() => () async {\n    //   //     //     if (await showExperimentalNotice()) {\n    //   //     //       return await ref.read(connectionNotifierProvider.notifier).toggleConnection();\n    //   //     //     }\n    //   //     //   },\n    //   //     // AsyncData(value: Connected()) => () async {\n    //   //     //     if (requiresReconnect == true && await showExperimentalNotice()) {\n    //   //     //       return await ref.read(connectionNotifierProvider.notifier).reconnect(await ref.read(activeProfileProvider.future));\n    //   //     //     }\n    //   //     //     return await ref.read(connectionNotifierProvider.notifier).toggleConnection();\n    //   //     //   },\n    //   //     _ => () {},\n    //   //   },\n    //   //   // enabled: switch (connectionStatus) {\n    //   //   //   AsyncData(value: Connected()) || AsyncData(value: Disconnected()) || AsyncError() => true,\n    //   //   //   _ => false,\n    //   //   // },\n    //   //   // label: switch (connectionStatus) {\n    //   //   //   AsyncData(value: Connected()) when requiresReconnect == true => t.connection.reconnect,\n    //   //   //   AsyncData(value: Connected()) when delay <= 0 || delay >= 65000 => t.connection.connecting,\n    //   //   //   AsyncData(value: final status) => status.present(t),\n    //   //   //   _ => \"\",\n    //   //   // },\n    //   //   color: switch (connectionStatus) {\n    //   //     AsyncData(value: Connected()) when requiresReconnect == true => Colors.teal,\n    //   //     AsyncData(value: Connected()) when delay <= 0 || delay >= 65000 => Color.fromARGB(255, 157, 139, 1),\n    //   //     AsyncData(value: Connected()) => Colors.green.shade900,\n    //   //     AsyncData(value: _) => Colors.indigo.shade700, // Color(0xFF3446A5), //buttonTheme.idleColor!,\n    //   //     _ => Colors.red,\n    //   //   },\n\n    //   //   animated: true ||\n    //   //       switch (connectionStatus) {\n    //   //         AsyncData(value: Connected()) when requiresReconnect == true => false,\n    //   //         AsyncData(value: Connected()) when delay <= 0 || delay >= 65000 => false,\n    //   //         AsyncData(value: Connected()) => true,\n    //   //         AsyncData(value: _) => true,\n    //   //         _ => false,\n    //   //       },\n    //   //   animationValue: animationValue,\n    //   // );\n    // }\n    var secureLabel =\n        (ref.watch(ConfigOptions.enableWarp) && ref.watch(ConfigOptions.warpDetourMode) == WarpDetourMode.warpOverProxy)\n        ? t.connection.secure\n        : \"\";\n    if (delay <= 0 || delay > 65000 || connectionStatus.value != const Connected()) {\n      secureLabel = \"\";\n    }\n    return _ConnectionButton(\n      onTap: switch (connectionStatus) {\n        AsyncData(value: Connected()) when requiresReconnect == true => () async {\n          final activeProfile = await ref.read(activeProfileProvider.future);\n          return await ref.read(connectionNotifierProvider.notifier).reconnect(activeProfile);\n        },\n        AsyncData(value: Disconnected()) || AsyncError() => () async {\n          if (ref.read(activeProfileProvider).valueOrNull == null) {\n            await ref.read(dialogNotifierProvider.notifier).showNoActiveProfile();\n            ref.read(bottomSheetsNotifierProvider.notifier).showAddProfile();\n          }\n          if (await ref.read(dialogNotifierProvider.notifier).showExperimentalFeatureNotice()) {\n            return await ref.read(connectionNotifierProvider.notifier).toggleConnection();\n          }\n        },\n        AsyncData(value: Connected()) => () async {\n          if (requiresReconnect == true &&\n              await ref.read(dialogNotifierProvider.notifier).showExperimentalFeatureNotice()) {\n            return await ref\n                .read(connectionNotifierProvider.notifier)\n                .reconnect(await ref.read(activeProfileProvider.future));\n          }\n          return await ref.read(connectionNotifierProvider.notifier).toggleConnection();\n        },\n        _ => () {},\n      },\n      enabled: switch (connectionStatus) {\n        AsyncData(value: Connected()) || AsyncData(value: Disconnected()) || AsyncError() => true,\n        _ => false,\n      },\n      label: switch (connectionStatus) {\n        AsyncData(value: Connected()) when requiresReconnect == true => t.connection.reconnect,\n        AsyncData(value: Connected()) when delay <= 0 || delay >= 65000 => t.connection.connecting,\n        AsyncData(value: final status) => status.present(t),\n        _ => \"\",\n      },\n      buttonColor: switch (connectionStatus) {\n        AsyncData(value: Connected()) when requiresReconnect == true => Colors.teal,\n        AsyncData(value: Connected()) when delay <= 0 || delay >= 65000 => const Color.fromARGB(255, 185, 176, 103),\n        AsyncData(value: Connected()) => buttonTheme.connectedColor!,\n        AsyncData(value: _) => buttonTheme.idleColor!,\n        _ => Colors.red,\n      },\n      image: switch (connectionStatus) {\n        AsyncData(value: Connected()) when requiresReconnect == true => Assets.images.disconnectNorouz,\n        AsyncData(value: Connected()) => Assets.images.connectNorouz,\n        AsyncData(value: _) => Assets.images.disconnectNorouz,\n        _ => Assets.images.disconnectNorouz,\n        AsyncData(value: Disconnected()) || AsyncError() => Assets.images.disconnectNorouz,\n        AsyncData(value: Connected()) => Assets.images.connectNorouz,\n        _ => Assets.images.disconnectNorouz,\n      },\n      newButtonColor: switch (connectionStatus) {\n        AsyncData(value: Connected()) when requiresReconnect == true => Colors.teal,\n        AsyncData(value: Connected()) when delay <= 0 || delay >= 65000 => const Color.fromARGB(255, 185, 176, 103),\n        AsyncData(value: Connected()) => buttonTheme.connectedColor!,\n        AsyncData(value: _) => buttonTheme.idleColor!,\n        _ => Colors.red,\n      },\n      animated: switch (connectionStatus) {\n        AsyncData(value: Connected()) when requiresReconnect == true => false,\n        AsyncData(value: Connected()) when delay <= 0 || delay >= 65000 => false,\n        AsyncData(value: Connected()) => true,\n        AsyncData(value: _) => true,\n        _ => false,\n      },\n      useImage: today.day >= 19 && today.day <= 23 && today.month == 3,\n      secureLabel: secureLabel,\n    );\n  }\n}\n\nclass _ConnectionButton extends StatelessWidget {\n  const _ConnectionButton({\n    required this.onTap,\n    required this.enabled,\n    required this.label,\n    required this.buttonColor,\n    required this.image,\n    required this.useImage,\n    required this.newButtonColor,\n    required this.animated,\n    required this.secureLabel,\n  });\n\n  final VoidCallback onTap;\n  final bool enabled;\n  final String label;\n  final Color buttonColor;\n  final AssetGenImage image;\n  final bool useImage;\n  final String secureLabel;\n\n  final Color newButtonColor;\n\n  final bool animated;\n\n  @override\n  Widget build(BuildContext context) {\n    return Column(\n      mainAxisAlignment: MainAxisAlignment.center,\n      children: [\n        // CircleDesignWidget(newButtonColor: newButtonColor, onTap: onTap, animated: animated),\n        Semantics(\n          button: true,\n          enabled: enabled,\n          label: label,\n          child: Container(\n            clipBehavior: Clip.antiAlias,\n            decoration: BoxDecoration(\n              shape: BoxShape.circle,\n              boxShadow: [BoxShadow(blurRadius: 16, color: buttonColor.withValues(alpha: .5))],\n            ),\n            width: 148,\n            height: 148,\n            child: Material(\n              key: const ValueKey(\"home_connection_button\"),\n              shape: const CircleBorder(),\n              color: Colors.white,\n              child: InkWell(\n                focusColor: Colors.grey,\n                onTap: onTap,\n                child: Padding(\n                  padding: const EdgeInsets.all(36),\n                  child: TweenAnimationBuilder(\n                    tween: ColorTween(end: buttonColor),\n                    duration: const Duration(milliseconds: 250),\n                    builder: (context, value, child) {\n                      if (useImage) {\n                        return image.image();\n                      } else {\n                        return Assets.images.logo.svg(colorFilter: ColorFilter.mode(value!, BlendMode.srcIn));\n                      }\n                    },\n                  ),\n                ),\n              ),\n            ).animate(target: enabled ? 0 : 1).blurXY(end: 1),\n          ).animate(target: enabled ? 0 : 1).scaleXY(end: .88, curve: Curves.easeIn),\n        ),\n        const Gap(16),\n        ExcludeSemantics(\n          child: Column(\n            mainAxisAlignment: MainAxisAlignment.center,\n            children: [\n              AnimatedText(label, style: Theme.of(context).textTheme.titleMedium),\n              if (secureLabel.isNotEmpty) ...[\n                Row(\n                  mainAxisAlignment: MainAxisAlignment.center,\n                  children: [\n                    // const Gap(8),\n                    Icon(FontAwesomeIcons.shieldHalved, size: 16, color: Theme.of(context).colorScheme.secondary),\n                    const Gap(4),\n                    Text(\n                      secureLabel,\n                      style: Theme.of(\n                        context,\n                      ).textTheme.titleSmall?.copyWith(color: Theme.of(context).colorScheme.secondary),\n                    ),\n                  ],\n                ),\n              ],\n            ],\n          ),\n        ),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/home/widget/empty_profiles_home_body.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/router/bottom_sheets/bottom_sheets_notifier.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass EmptyProfilesHomeBody extends HookConsumerWidget {\n  const EmptyProfilesHomeBody({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    return SliverFillRemaining(\n      hasScrollBody: false,\n      child: Column(\n        mainAxisAlignment: MainAxisAlignment.center,\n        children: [\n          Text(t.dialogs.noActiveProfile.msg),\n          const Gap(16),\n          ElevatedButton(\n            onPressed: () => ref.read(bottomSheetsNotifierProvider.notifier).showAddProfile(),\n            // icon: const Icon(FluentIcons.add_24_regular),\n            child: Text(t.pages.profiles.add),\n          ),\n        ],\n      ),\n    );\n  }\n}\n\n// class EmptyActiveProfileHomeBody extends HookConsumerWidget {\n//   const EmptyActiveProfileHomeBody({super.key});\n\n//   @override\n//   Widget build(BuildContext context, WidgetRef ref) {\n//     final t = ref.watch(translationsProvider).requireValue;\n\n//     return SliverFillRemaining(\n//       hasScrollBody: false,\n//       child: Column(\n//         mainAxisAlignment: MainAxisAlignment.center,\n//         children: [\n//           Text(t.home.noActiveProfileMsg),\n//           const Gap(16),\n//           OutlinedButton(\n//             onPressed: () => const ProfilesOverviewRoute().push(context),\n//             child: Text(t.profile.overviewPageTitle),\n//           ),\n//         ],\n//       ),\n//     );\n//   }\n// }\n"
  },
  {
    "path": "lib/features/home/widget/home_page.dart",
    "content": "import 'package:dartx/dartx.dart';\nimport 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/app_info/app_info_provider.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/router/bottom_sheets/bottom_sheets_notifier.dart';\nimport 'package:hiddify/features/home/widget/connection_button.dart';\nimport 'package:hiddify/features/profile/notifier/active_profile_notifier.dart';\nimport 'package:hiddify/features/profile/widget/profile_tile.dart';\nimport 'package:hiddify/features/proxy/active/active_proxy_card.dart';\nimport 'package:hiddify/features/proxy/active/active_proxy_delay_indicator.dart';\nimport 'package:hiddify/gen/assets.gen.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:sliver_tools/sliver_tools.dart';\n\nclass HomePage extends HookConsumerWidget {\n  const HomePage({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final theme = Theme.of(context);\n    final t = ref.watch(translationsProvider).requireValue;\n    // final hasAnyProfile = ref.watch(hasAnyProfileProvider);\n    final activeProfile = ref.watch(activeProfileProvider);\n\n    return Scaffold(\n      appBar: AppBar(\n        // leading: (RootScaffold.stateKey.currentState?.hasDrawer ?? false) && showDrawerButton(context)\n        //     ? DrawerButton(\n        //         onPressed: () {\n        //           RootScaffold.stateKey.currentState?.openDrawer();\n        //         },\n        //       )\n        //     : null,\n        title: Row(\n          children: [\n            Assets.images.logo.svg(height: 24),\n            const Gap(8),\n            Text.rich(\n              TextSpan(\n                children: [\n                  TextSpan(text: t.common.appTitle),\n                  const TextSpan(text: \" \"),\n                  const WidgetSpan(child: AppVersionLabel(), alignment: PlaceholderAlignment.middle),\n                ],\n              ),\n            ),\n          ],\n        ),\n        actions: [\n          // IconButton(\n          //     onPressed: () => const QuickSettingsRoute().push(context),\n          //     icon: const Icon(FluentIcons.options_24_filled),\n          //     material: (context, platform) => MaterialIconButtonData(\n          //           tooltip: t.config.quickSettings,\n          //         )),\n          // IconButton(\n          //     onPressed: () => const AddProfileRoute().push(context),\n          //     icon: const Icon(FluentIcons.add_circle_24_filled),\n          //     material: (context, platform) => MaterialIconButtonData(\n          //           tooltip: t.profile.add.buttonText,\n          //         )),\n          Semantics(\n            key: const ValueKey(\"profile_quick_settings\"),\n            label: t.pages.home.quickSettings,\n            child: IconButton(\n              icon: Icon(Icons.tune_rounded, color: theme.colorScheme.primary),\n              onPressed: () => ref.read(bottomSheetsNotifierProvider.notifier).showQuickSettings(),\n            ),\n          ),\n          const Gap(8),\n          Semantics(\n            key: const ValueKey(\"profile_add_button\"),\n            label: t.pages.profiles.add,\n            child: IconButton(\n              icon: Icon(Icons.add_rounded, color: theme.colorScheme.primary),\n              onPressed: () => ref.read(bottomSheetsNotifierProvider.notifier).showAddProfile(),\n            ),\n          ),\n          const Gap(8),\n        ],\n      ),\n      body: Container(\n        decoration: BoxDecoration(\n          image: DecorationImage(\n            image: const AssetImage('assets/images/world_map.png'), // Replace with your image path\n            fit: BoxFit.cover,\n            opacity: 0.09,\n            colorFilter: theme.brightness == Brightness.dark\n                ? ColorFilter.mode(Colors.white.withValues(alpha: .15), BlendMode.srcIn) //\n                : ColorFilter.mode(\n                    Colors.grey.withValues(alpha: 1),\n                    BlendMode.srcATop,\n                  ), // Apply white tint in dark mode\n          ),\n        ),\n        child: Stack(\n          alignment: Alignment.center,\n          children: [\n            Center(\n              child: ConstrainedBox(\n                constraints: const BoxConstraints(\n                  maxWidth: 600, // Set the maximum width here\n                ),\n                child: CustomScrollView(\n                  slivers: [\n                    // switch (activeProfile) {\n                    // AsyncData(value: final profile?) =>\n                    MultiSliver(\n                      children: [\n                        // const Gap(100),\n                        switch (activeProfile) {\n                          AsyncData(value: final profile?) => ProfileTile(\n                            profile: profile,\n                            isMain: true,\n                            margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),\n                            color: Theme.of(context).colorScheme.surfaceContainer,\n                          ),\n                          _ => const Text(\"\"),\n                        },\n                        const SliverFillRemaining(\n                          hasScrollBody: false,\n                          child: Column(\n                            mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                            children: [\n                              Expanded(\n                                child: Column(\n                                  mainAxisSize: MainAxisSize.min,\n                                  mainAxisAlignment: MainAxisAlignment.center,\n                                  children: [ConnectionButton(), ActiveProxyDelayIndicator()],\n                                ),\n                              ),\n                              ActiveProxyFooter(),\n                            ],\n                          ),\n                        ),\n                      ],\n                    ),\n                    // AsyncData() => switch (hasAnyProfile) {\n                    //     AsyncData(value: true) => const EmptyActiveProfileHomeBody(),\n                    //     _ => const EmptyProfilesHomeBody(),\n                    //   },\n                    // AsyncError(:final error) => SliverErrorBodyPlaceholder(t.presentShortError(error)),\n                    // _ => const SliverToBoxAdapter(),\n                    // },\n                  ],\n                ),\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n\nclass AppVersionLabel extends HookConsumerWidget {\n  const AppVersionLabel({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final theme = Theme.of(context);\n\n    final version = ref.watch(appInfoProvider).requireValue.presentVersion;\n    if (version.isBlank) return const SizedBox();\n\n    return Semantics(\n      label: t.common.version,\n      button: false,\n      child: Container(\n        decoration: BoxDecoration(color: theme.colorScheme.secondaryContainer, borderRadius: BorderRadius.circular(4)),\n        padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),\n        child: Text(\n          version,\n          textDirection: TextDirection.ltr,\n          style: theme.textTheme.bodySmall?.copyWith(color: theme.colorScheme.onSecondaryContainer),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/home/widget/new_con_button.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter_animate/flutter_animate.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/widget/animated_text.dart';\n\nclass CircleDesignWidget extends StatelessWidget {\n  final double animationValue;\n  final Color color;\n  final VoidCallback onTap;\n  final bool enabled;\n  final String label;\n\n  const CircleDesignWidget({\n    Key? key,\n    required this.animationValue,\n    required this.color,\n    required this.onTap,\n    required this.enabled,\n    required this.label,\n  }) : super(key: key);\n  // GestureDetector(\n  //       onTap: onTap,\n  //       child: CustomPaint(\n  //         size: const Size(168, 168),\n  //         painter: CirclePainter(\n  //           animationValue: animationValue,\n  //           baseColor: color,\n  //         ),\n  //       )\n  @override\n  Widget build(BuildContext context) {\n    return Column(\n      mainAxisAlignment: MainAxisAlignment.center,\n      children: [\n        // CircleDesignWidget(newButtonColor: newButtonColor, onTap: onTap, animated: animated),\n        Semantics(\n          button: true,\n          enabled: enabled,\n          label: label,\n          child: Container(\n            clipBehavior: Clip.antiAlias,\n            decoration: const BoxDecoration(\n              shape: BoxShape.circle,\n              // boxShadow: [\n              //   BoxShadow(\n              //     blurRadius: 16,\n              //     color: color.withOpacity(0.5),\n              //   ),\n              // ],\n            ),\n            width: 168,\n            height: 168,\n            child: Material(\n              key: const ValueKey(\"home_connection_button\"),\n              shape: const CircleBorder(),\n              // color: Colors.white,\n              child: InkWell(\n                onTap: onTap,\n                child: Padding(\n                  padding: const EdgeInsets.all(0),\n                  child: TweenAnimationBuilder(\n                    tween: ColorTween(end: color),\n                    duration: const Duration(milliseconds: 250),\n                    builder: (context, value, child) {\n                      return CustomPaint(\n                        painter: CirclePainter(animationValue: animationValue, baseColor: value!),\n                      );\n                      // return Assets.images.logo.svg(\n                      //   colorFilter: ColorFilter.mode(\n                      //     value!,\n                      //     BlendMode.srcIn,\n                      //   ),\n                      // );\n                    },\n                  ),\n                ),\n              ),\n            ).animate(target: enabled ? 0 : 1).blurXY(end: 1),\n          ).animate(target: enabled ? 0 : 1).scaleXY(end: .88, curve: Curves.easeIn),\n        ),\n        const Gap(16),\n        ExcludeSemantics(child: AnimatedText(label, style: Theme.of(context).textTheme.titleMedium)),\n      ],\n    );\n  }\n}\n\nclass CirclePainter extends CustomPainter {\n  final double animationValue;\n  final Color baseColor;\n\n  CirclePainter({required this.animationValue, required this.baseColor});\n\n  @override\n  void paint(Canvas canvas, Size size) {\n    final double cx = size.width / 2;\n    final double cy = size.height / 2;\n\n    final innerCircleColor = [baseColor.withAlpha(230), baseColor];\n\n    // Outer circle (pulsing animation for connecting state)\n    final Paint outerCirclePaint = Paint()\n      ..color = baseColor.withOpacity(0.15)\n      ..style = PaintingStyle.fill;\n    final double outerRadius = 84 * animationValue;\n\n    canvas.drawCircle(Offset(cx, cy), outerRadius, outerCirclePaint);\n\n    // Middle circle\n    final Paint middleCirclePaint = Paint()\n      ..color = baseColor.withOpacity(.3)\n      ..style = PaintingStyle.fill;\n    final double middleRadius = 60 * animationValue + (1 - animationValue) / 3;\n    canvas.drawCircle(Offset(cx, cy), middleRadius, middleCirclePaint);\n\n    // Inner circle with gradient\n    final Paint innerCirclePaint = Paint()\n      ..shader = LinearGradient(\n        begin: Alignment.topCenter,\n        end: Alignment.bottomCenter,\n        colors: innerCircleColor,\n      ).createShader(Rect.fromCircle(center: Offset(cx, cy), radius: 36));\n    final double innerRadius = 36;\n    canvas.drawCircle(Offset(cx, cy), innerRadius, innerCirclePaint);\n\n    // Draw path and vertical line (same as original)\n    final Paint pathPaint = Paint()\n      ..color = Colors.white\n      ..style = PaintingStyle.stroke\n      ..strokeWidth = 3.80952\n      ..strokeCap = StrokeCap.round\n      ..strokeJoin = StrokeJoin.round;\n\n    final Path curvePath = Path()\n      ..moveTo(92.4867, 75.52)\n      ..cubicTo(94.1645, 77.1984, 95.307, 79.3366, 95.7697, 81.6643)\n      ..cubicTo(96.2324, 83.9919, 95.9946, 86.4045, 95.0862, 88.597)\n      ..cubicTo(94.1778, 90.7895, 92.6397, 92.6634, 90.6664, 93.9818)\n      ..cubicTo(88.6931, 95.3002, 86.3732, 96.0039, 84, 96.0039)\n      ..cubicTo(81.6268, 96.0039, 79.3069, 95.3002, 77.3336, 93.9818)\n      ..cubicTo(75.3603, 92.6634, 73.8222, 90.7895, 72.9138, 88.597)\n      ..cubicTo(72.0055, 86.4045, 71.7676, 83.9919, 72.2303, 81.6643)\n      ..cubicTo(72.693, 79.3366, 73.8355, 77.1984, 75.5133, 75.52);\n    canvas.drawPath(curvePath, pathPaint);\n\n    final Path linePath = Path()\n      ..moveTo(84.0066, 72)\n      ..lineTo(84.0066, 82.6667);\n\n    // Draw the vertical line\n    canvas.drawPath(linePath, pathPaint);\n  }\n\n  @override\n  bool shouldRepaint(CustomPainter oldDelegate) => true;\n}\n"
  },
  {
    "path": "lib/features/home/widget/new_connection_button.dart",
    "content": "import 'package:flutter/material.dart';\n\nenum ConnectionStateStatus { disconnected, connecting, connected, error }\n\nclass CircleDesignWidget extends StatefulWidget {\n  @override\n  _CircleDesignWidgetState createState() => _CircleDesignWidgetState();\n}\n\nclass _CircleDesignWidgetState extends State<CircleDesignWidget> with SingleTickerProviderStateMixin {\n  ConnectionStateStatus _currentState = ConnectionStateStatus.disconnected;\n  late AnimationController _controller;\n  late Animation<double> _animation;\n\n  @override\n  void initState() {\n    super.initState();\n\n    // Animation controller for the connecting state\n    _controller = AnimationController(duration: const Duration(seconds: 4), vsync: this)..repeat(reverse: true);\n\n    _animation = Tween<double>(begin: 0.8, end: 1).animate(_controller)\n      ..addListener(() {\n        setState(() {});\n      });\n  }\n\n  @override\n  void dispose() {\n    _controller.dispose();\n    super.dispose();\n  }\n\n  void changeState(ConnectionStateStatus state) {\n    setState(() {\n      _currentState = state;\n      if (state == ConnectionStateStatus.connecting || state == ConnectionStateStatus.connected) {\n        _controller.repeat(reverse: true);\n      } else {\n        _controller.stop();\n      }\n    });\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return GestureDetector(\n      onTap: () {\n        // Change the state for demo purposes\n        switch (_currentState) {\n          case ConnectionStateStatus.disconnected:\n            changeState(ConnectionStateStatus.connecting);\n            break;\n          case ConnectionStateStatus.connecting:\n            changeState(ConnectionStateStatus.connected);\n            break;\n          case ConnectionStateStatus.connected:\n            changeState(ConnectionStateStatus.error);\n            break;\n          case ConnectionStateStatus.error:\n            changeState(ConnectionStateStatus.disconnected);\n            break;\n        }\n      },\n      child: CustomPaint(\n        size: const Size(168, 168),\n        painter: CirclePainter(currentState: _currentState, animationValue: _animation.value),\n      ),\n    );\n  }\n}\n\nclass CirclePainter extends CustomPainter {\n  final ConnectionStateStatus currentState;\n  final double animationValue;\n\n  CirclePainter({required this.currentState, required this.animationValue});\n\n  @override\n  void paint(Canvas canvas, Size size) {\n    final double cx = size.width / 2;\n    final double cy = size.height / 2;\n\n    Color baseColor;\n    var innerCircleColor = [const Color(0xFF455FE9), const Color(0xFF3446A5)];\n    if (currentState == ConnectionStateStatus.connected) {\n      baseColor = Colors.green.shade900;\n    } else if (currentState == ConnectionStateStatus.error) {\n      baseColor = Colors.red.shade900;\n    } else {\n      // baseColor = const Color(0xFFB8C7F4);\n      baseColor = const Color(0xFF3446A5);\n    }\n    innerCircleColor = [\n      baseColor.withAlpha(230),\n      baseColor,\n      // Color.fromARGB(73, 27, 80, 43),\n      // Color.fromARGB(71, 12, 48, 21),\n    ];\n\n    // Outer circle (pulsing animation for connecting state)\n    final Paint outerCirclePaint = Paint()\n      ..color = baseColor.withOpacity(0.15)\n      ..style = PaintingStyle.fill;\n    // double outerRadius = (size.width / 2) * (currentState == ConnectionStateStatus.connecting ? animationValue : 1);\n    final double outerRadius =\n        84 *\n        ([ConnectionStateStatus.connecting, ConnectionStateStatus.connected].contains(currentState)\n            ? animationValue\n            : 1);\n\n    canvas.drawCircle(Offset(cx, cy), outerRadius, outerCirclePaint);\n\n    // Middle circle\n    final Paint middleCirclePaint = Paint()\n      ..color = baseColor.withOpacity(.3)\n      ..style = PaintingStyle.fill;\n    final double middleRadius =\n        60 *\n        ([ConnectionStateStatus.connecting, ConnectionStateStatus.connected].contains(currentState)\n            ? animationValue + (1 - animationValue) / 3\n            : 1);\n    canvas.drawCircle(Offset(cx, cy), middleRadius, middleCirclePaint);\n\n    // Inner circle with gradient\n    final Paint innerCirclePaint = Paint()\n      ..shader = LinearGradient(\n        begin: Alignment.topCenter,\n        end: Alignment.bottomCenter,\n        colors: innerCircleColor,\n      ).createShader(Rect.fromCircle(center: Offset(cx, cy), radius: 36));\n    final double innerRadius = 36; //* (currentState == ConnectionStateStatus.connecting ? animationValue : 1);\n    canvas.drawCircle(Offset(cx, cy), innerRadius, innerCirclePaint);\n    final Paint pathPaint = Paint()\n      ..color = Colors.white\n      ..style = PaintingStyle.stroke\n      ..strokeWidth = 3.80952\n      ..strokeCap = StrokeCap.round\n      ..strokeJoin = StrokeJoin.round;\n\n    final Path curvePath = Path()\n      ..moveTo(92.4867, 75.52)\n      ..cubicTo(94.1645, 77.1984, 95.307, 79.3366, 95.7697, 81.6643)\n      ..cubicTo(96.2324, 83.9919, 95.9946, 86.4045, 95.0862, 88.597)\n      ..cubicTo(94.1778, 90.7895, 92.6397, 92.6634, 90.6664, 93.9818)\n      ..cubicTo(88.6931, 95.3002, 86.3732, 96.0039, 84, 96.0039)\n      ..cubicTo(81.6268, 96.0039, 79.3069, 95.3002, 77.3336, 93.9818)\n      ..cubicTo(75.3603, 92.6634, 73.8222, 90.7895, 72.9138, 88.597)\n      ..cubicTo(72.0055, 86.4045, 71.7676, 83.9919, 72.2303, 81.6643)\n      ..cubicTo(72.693, 79.3366, 73.8355, 77.1984, 75.5133, 75.52);\n    canvas.drawPath(curvePath, pathPaint);\n    // Vertical line\n    final Path linePath = Path()\n      ..moveTo(84.0066, 72)\n      ..lineTo(84.0066, 82.6667);\n\n    // Draw the vertical line\n    canvas.drawPath(linePath, pathPaint);\n  }\n\n  @override\n  bool shouldRepaint(CustomPainter oldDelegate) => true;\n}\n"
  },
  {
    "path": "lib/features/intro/widget/intro_page.dart",
    "content": "import 'dart:async';\nimport 'dart:io';\n\nimport 'package:flutter/gestures.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/analytics/analytics_controller.dart';\nimport 'package:hiddify/core/http_client/dio_http_client.dart';\nimport 'package:hiddify/core/localization/locale_preferences.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/model/region.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/features/common/general_pref_tiles.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/widget/preference_tile.dart';\nimport 'package:hiddify/gen/assets.gen.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass IntroPage extends HookConsumerWidget with PresLogger {\n  const IntroPage({super.key});\n\n  static bool locationInfoLoaded = false;\n\n  // for focus management\n  KeyEventResult _handleKeyEvent(KeyEvent event, String key) {\n    if (KeyboardConst.select.contains(event.logicalKey) && event is KeyUpEvent) {\n      UriUtils.tryLaunch(Uri.parse(IntroConst.url[key]!));\n      return KeyEventResult.handled;\n    }\n    return KeyEventResult.ignored;\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final theme = Theme.of(context);\n\n    final isStarting = useState(false);\n\n    if (!locationInfoLoaded) {\n      autoSelectRegion(ref).then((value) => loggy.debug(\"Auto Region selection finished!\"));\n      locationInfoLoaded = true;\n    }\n\n    // for focus management\n    final focusStates = <String, ValueNotifier<bool>>{\n      IntroConst.termsAndConditionsKey: useState<bool>(false),\n      IntroConst.githubKey: useState<bool>(false),\n      IntroConst.licenseKey: useState<bool>(false),\n    };\n    final focusNodes = <String, FocusNode>{\n      IntroConst.termsAndConditionsKey: useFocusNode(),\n      IntroConst.githubKey: useFocusNode(),\n      IntroConst.licenseKey: useFocusNode(),\n    };\n    useEffect(() {\n      for (final entry in focusNodes.entries) {\n        entry.value.addListener(() => focusStates[entry.key]!.value = entry.value.hasPrimaryFocus);\n      }\n      return null;\n    }, []);\n\n    return Scaffold(\n      body: Center(\n        child: ScrollConfiguration(\n          behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),\n          child: SingleChildScrollView(\n            child: ConstrainedBox(\n              constraints: const BoxConstraints(maxWidth: 620),\n              child: Column(\n                mainAxisSize: MainAxisSize.min,\n                children: [\n                  LayoutBuilder(\n                    builder: (context, constraints) {\n                      final width = constraints.maxWidth > IntroConst.maxwidth\n                          ? IntroConst.maxwidth\n                          : constraints.maxWidth;\n                      final size = width * 0.4;\n                      return Assets.images.logo.svg(width: size, height: size);\n                    },\n                  ),\n                  const Gap(16),\n                  Padding(\n                    padding: const EdgeInsets.symmetric(horizontal: 16),\n                    child: Text(\n                      t.intro.banner,\n                      style: theme.textTheme.bodyLarge,\n                      maxLines: 1,\n                      overflow: TextOverflow.ellipsis,\n                    ),\n                  ),\n                  const Gap(24),\n                  const LocalePrefTile(),\n                  ChoicePreferenceWidget(\n                    selected: ref.watch(ConfigOptions.region),\n                    preferences: ref.watch(ConfigOptions.region.notifier),\n                    choices: Region.values,\n                    title: t.pages.settings.routing.region,\n                    showFlag: true,\n                    icon: Icons.place_rounded,\n                    presentChoice: (value) => value.present(t),\n                    onChanged: (val) async {\n                      await ref.read(ConfigOptions.directDnsAddress.notifier).reset();\n                    },\n                  ),\n                  const EnableAnalyticsPrefTile(),\n                  const Gap(24),\n                  Focus(\n                    focusNode: focusNodes[IntroConst.termsAndConditionsKey],\n                    onKeyEvent: (node, event) => _handleKeyEvent(event, IntroConst.termsAndConditionsKey),\n                    child: Text.rich(\n                      t.intro.termsAndPolicyCaution(\n                        tap: (text) => TextSpan(\n                          text: text,\n                          style: TextStyle(\n                            color: focusStates[IntroConst.termsAndConditionsKey]!.value ? Colors.green : Colors.blue,\n                          ),\n                          recognizer: TapGestureRecognizer()\n                            ..onTap = () async {\n                              await UriUtils.tryLaunch(Uri.parse(Constants.termsAndConditionsUrl));\n                            },\n                        ),\n                      ),\n                      style: theme.textTheme.bodySmall,\n                    ),\n                  ),\n                  const Gap(8),\n                  Focus(\n                    focusNode: focusNodes[IntroConst.githubKey],\n                    onKeyEvent: (node, event) => _handleKeyEvent(event, IntroConst.githubKey),\n                    child: Text.rich(\n                      t.intro.info(\n                        tap_source: (text) => TextSpan(\n                          text: text,\n                          style: TextStyle(\n                            color: focusStates[IntroConst.githubKey]!.value ? Colors.green : Colors.blue,\n                          ),\n                          recognizer: TapGestureRecognizer()\n                            ..onTap = () async {\n                              await UriUtils.tryLaunch(Uri.parse(Constants.githubUrl));\n                            },\n                        ),\n                        tap_license: (text) => TextSpan(\n                          text: text,\n                          style: TextStyle(\n                            color: focusStates[IntroConst.githubKey]!.value ? Colors.green : Colors.blue,\n                          ),\n                          recognizer: TapGestureRecognizer()\n                            ..onTap = () async {\n                              await UriUtils.tryLaunch(Uri.parse(Constants.licenseUrl));\n                            },\n                        ),\n                      ),\n                      style: theme.textTheme.bodySmall,\n                    ),\n                  ),\n                  // only for managing license node focus\n                  Focus(\n                    focusNode: focusNodes[IntroConst.licenseKey],\n                    onKeyEvent: (node, event) => _handleKeyEvent(event, IntroConst.licenseKey),\n                    child: const Gap(88),\n                  ),\n                ],\n              ),\n            ),\n          ),\n        ),\n      ),\n      floatingActionButton: FloatingActionButton.extended(\n        icon: isStarting.value\n            ? const SizedBox(width: 24, height: 24, child: CircularProgressIndicator())\n            : const Icon(Icons.rocket_launch),\n        label: Text(t.common.start, style: theme.textTheme.titleMedium),\n        onPressed: () async {\n          if (isStarting.value) return;\n          isStarting.value = true;\n          if (!ref.read(analyticsControllerProvider).requireValue) {\n            loggy.info(\"disabling analytics per user request\");\n            try {\n              await ref.read(analyticsControllerProvider.notifier).disableAnalytics();\n            } catch (error, stackTrace) {\n              loggy.error(\"could not disable analytics\", error, stackTrace);\n            }\n          }\n          await ref.read(Preferences.introCompleted.notifier).update(true);\n        },\n      ),\n    );\n  }\n\n  Future<void> autoSelectRegion(WidgetRef ref) async {\n    try {\n      final countryCode = RegionDetector.detect();\n      final regionLocale = _getRegionLocale(countryCode);\n      loggy.debug('Timezone Region: ${regionLocale.region} Locale: ${regionLocale.locale}');\n      await ref.read(ConfigOptions.region.notifier).update(regionLocale.region);\n      await ref.watch(ConfigOptions.directDnsAddress.notifier).reset();\n      await ref.read(localePreferencesProvider.notifier).changeLocale(regionLocale.locale);\n      return;\n    } catch (e) {\n      loggy.warning('Could not get the local country code based on timezone', e);\n    }\n\n    try {\n      final DioHttpClient client = DioHttpClient(\n        timeout: const Duration(seconds: 2),\n        userAgent: \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0\",\n        debug: true,\n      );\n      final response = await client.get<Map<String, dynamic>>('https://api.ip.sb/geoip/');\n\n      if (response.statusCode == 200) {\n        final jsonData = response.data!;\n        final regionLocale = _getRegionLocale(jsonData['country_code']?.toString() ?? \"\");\n\n        loggy.debug('Region: ${regionLocale.region} Locale: ${regionLocale.locale}');\n        await ref.read(ConfigOptions.region.notifier).update(regionLocale.region);\n        await ref.read(localePreferencesProvider.notifier).changeLocale(regionLocale.locale);\n      } else {\n        loggy.warning('Request failed with status: ${response.statusCode}');\n      }\n    } catch (e) {\n      loggy.warning('Could not get the local country code from ip');\n    }\n  }\n\n  RegionLocale _getRegionLocale(String country) {\n    switch (country.toUpperCase()) {\n      case \"IR\":\n        return RegionLocale(Region.ir, AppLocale.fa);\n      case \"CN\":\n        return RegionLocale(Region.cn, AppLocale.zhCn);\n      case \"RU\":\n        return RegionLocale(Region.ru, AppLocale.ru);\n      case \"AF\":\n        return RegionLocale(Region.af, AppLocale.fa);\n      case \"BR\":\n        return RegionLocale(Region.br, AppLocale.ptBr);\n      case \"TR\":\n        return RegionLocale(Region.tr, AppLocale.tr);\n      default:\n        return RegionLocale(Region.other, AppLocale.en);\n    }\n  }\n}\n\nclass RegionLocale {\n  final Region region;\n  final AppLocale locale;\n\n  RegionLocale(this.region, this.locale);\n}\n\nclass RegionDetector {\n  /// Returns: 'IR' | 'AF' | 'CN' | 'TR' | 'RU' | 'BR' | 'US'\n  static String detect() {\n    final now = DateTime.now();\n    final offset = now.timeZoneOffset.inMinutes;\n    final tz = now.timeZoneName.toLowerCase().trim();\n\n    if (offset == 210) return 'IR';\n\n    if (offset == 270) {\n      final (_, country) = _parseLocale();\n      return country == 'IR' ? 'IR' : 'AF';\n    }\n\n    final fromName = _fromTzName(tz, offset);\n    if (fromName != null) return fromName;\n\n    final candidates = _candidatesForOffset(offset);\n    if (candidates.isEmpty) return 'US';\n\n    return _resolveByLocale(candidates);\n  }\n\n  static String? _fromTzName(String tz, int offset) {\n    if (tz.contains('/')) {\n      final city = tz.split('/').last.replaceAll(' ', '_');\n      final r = _ianaCities[city];\n      if (r != null) return r;\n    }\n\n    if (tz == 'irst' || tz == 'irdt' || tz.contains('iran')) return 'IR';\n\n    if (tz == 'aft' || tz.contains('afghanistan')) return 'AF';\n\n    if (tz == 'trt' || tz.contains('turkey') || tz.contains('istanbul')) {\n      return 'TR';\n    }\n\n    if (tz.contains('china') || tz.contains('beijing')) return 'CN';\n    if (tz == 'cst' && offset == 480) return 'CN';\n\n    if (_matchesRussiaTz(tz)) return 'RU';\n\n    if (_matchesBrazilTz(tz)) return 'BR';\n\n    return null;\n  }\n\n  static bool _matchesRussiaTz(String tz) {\n    if (tz.contains('russia') || tz.contains('moscow')) return true;\n\n    const abbrs = {'msk', 'yekt', 'omst', 'krat', 'irkt', 'yakt', 'vlat', 'magt', 'pett', 'sakt', 'sret'};\n    if (abbrs.contains(tz)) return true;\n\n    const winKeys = [\n      'ekaterinburg',\n      'kaliningrad',\n      'yakutsk',\n      'vladivostok',\n      'magadan',\n      'sakhalin',\n      'kamchatka',\n      'astrakhan',\n      'saratov',\n      'volgograd',\n      'altai',\n      'tomsk',\n      'transbaikal',\n      'n. central asia',\n      'north asia',\n    ];\n    return winKeys.any(tz.contains);\n  }\n\n  static bool _matchesBrazilTz(String tz) {\n    if (tz == 'brt' || tz == 'brst') return true;\n    if (tz.contains('brazil') || tz.contains('brasilia')) return true;\n\n    const winKeys = ['e. south america', 'central brazilian', 'tocantins', 'bahia'];\n    return winKeys.any(tz.contains);\n  }\n\n  static Set<String> _candidatesForOffset(int offset) {\n    final c = <String>{};\n\n    if (offset == 180) c.add('TR');\n\n    if (offset == 480) c.add('CN');\n\n    if (_ruOffsets.contains(offset)) c.add('RU');\n\n    if (_brOffsets.contains(offset)) c.add('BR');\n\n    return c;\n  }\n\n  static const _ruOffsets = {120, 180, 240, 300, 360, 420, 480, 540, 600, 660, 720};\n\n  static const _brOffsets = {-120, -180, -240, -300};\n\n  static String _resolveByLocale(Set<String> candidates) {\n    final (lang, country) = _parseLocale();\n\n    if (country != null && candidates.contains(country)) {\n      return country;\n    }\n\n    final regionFromLang = _langToRegion[lang];\n    if (regionFromLang != null && candidates.contains(regionFromLang)) {\n      return regionFromLang;\n    }\n\n    return 'US';\n  }\n\n  static (String, String?) _parseLocale() {\n    try {\n      final parts = Platform.localeName.split(RegExp(r'[_\\-.]'));\n      final lang = parts.first.toLowerCase();\n\n      String? country;\n      for (final p in parts.skip(1)) {\n        if (p.length == 2) {\n          country = p.toUpperCase();\n          break;\n        }\n      }\n\n      return (lang, country);\n    } catch (_) {\n      return ('en', null);\n    }\n  }\n\n  static const _langToRegion = <String, String>{'fa': 'IR', 'ps': 'AF', 'tr': 'TR', 'zh': 'CN', 'ru': 'RU', 'pt': 'BR'};\n\n  static const _ianaCities = <String, String>{\n    'tehran': 'IR',\n    'kabul': 'AF',\n    'istanbul': 'TR',\n    'shanghai': 'CN',\n    'chongqing': 'CN',\n    'urumqi': 'CN',\n    'harbin': 'CN',\n    'moscow': 'RU',\n    'kaliningrad': 'RU',\n    'samara': 'RU',\n    'yekaterinburg': 'RU',\n    'omsk': 'RU',\n    'novosibirsk': 'RU',\n    'barnaul': 'RU',\n    'tomsk': 'RU',\n    'krasnoyarsk': 'RU',\n    'irkutsk': 'RU',\n    'chita': 'RU',\n    'yakutsk': 'RU',\n    'vladivostok': 'RU',\n    'magadan': 'RU',\n    'sakhalin': 'RU',\n    'kamchatka': 'RU',\n    'anadyr': 'RU',\n    'volgograd': 'RU',\n    'saratov': 'RU',\n    'astrakhan': 'RU',\n    'sao_paulo': 'BR',\n    'fortaleza': 'BR',\n    'recife': 'BR',\n    'manaus': 'BR',\n    'belem': 'BR',\n    'cuiaba': 'BR',\n    'bahia': 'BR',\n    'rio_branco': 'BR',\n    'noronha': 'BR',\n    'porto_velho': 'BR',\n    'campo_grande': 'BR',\n  };\n}\n"
  },
  {
    "path": "lib/features/log/data/log_data_providers.dart",
    "content": "import 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/features/log/data/log_path_resolver.dart';\nimport 'package:hiddify/features/log/data/log_repository.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service_provider.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'log_data_providers.g.dart';\n\n@Riverpod(keepAlive: true)\nFuture<LogRepository> logRepository(LogRepositoryRef ref) async {\n  final repo = LogRepositoryImpl(\n    singbox: ref.watch(hiddifyCoreServiceProvider),\n    logPathResolver: ref.watch(logPathResolverProvider),\n  );\n  await repo.init().getOrElse((l) => throw l).run();\n  return repo;\n}\n\n@Riverpod(keepAlive: true)\nLogPathResolver logPathResolver(LogPathResolverRef ref) {\n  return LogPathResolver(ref.watch(appDirectoriesProvider).requireValue.workingDir);\n}\n"
  },
  {
    "path": "lib/features/log/data/log_parser.dart",
    "content": "// ignore_for_file: parameter_assignments\n\nimport 'package:dartx/dartx.dart';\nimport 'package:hiddify/features/log/model/log_entity.dart';\nimport 'package:hiddify/features/log/model/log_level.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart' as pb;\nimport 'package:tint/tint.dart';\n\nabstract class LogParser {\n  static LogEntity parseLogProto(pb.LogMessage message) {\n    final level = switch (message.level) {\n      pb.LogLevel.DEBUG => LogLevel.debug,\n      pb.LogLevel.INFO => LogLevel.info,\n      pb.LogLevel.WARNING => LogLevel.warn,\n      pb.LogLevel.ERROR => LogLevel.error,\n      pb.LogLevel.FATAL => LogLevel.fatal,\n      _ => LogLevel.debug,\n    };\n\n    return LogEntity(level: level, time: message.time.toDateTime(), message: message.message);\n  }\n\n  static LogEntity parseSingbox(String log) {\n    log = log.strip();\n    DateTime? time;\n    if (log.length > 25) {\n      time = DateTime.tryParse(log.substring(6, 25));\n    }\n    if (time != null) {\n      log = log.substring(26);\n    }\n    final level = LogLevel.values.firstOrNullWhere((e) {\n      if (log.startsWith(e.name.toUpperCase())) {\n        log = log.removePrefix(e.name.toUpperCase());\n        return true;\n      }\n      return false;\n    });\n    return LogEntity(level: level, time: time, message: log.trim());\n  }\n}\n"
  },
  {
    "path": "lib/features/log/data/log_path_resolver.dart",
    "content": "import 'dart:io';\n\nimport 'package:path/path.dart' as p;\n\nclass LogPathResolver {\n  const LogPathResolver(this._workingDir);\n\n  final Directory _workingDir;\n\n  Directory get directory => _workingDir;\n\n  File coreFile() {\n    return File(p.join(directory.path, \"box.log\"));\n  }\n\n  File appFile() {\n    return File(p.join(directory.path, \"app.log\"));\n  }\n}\n"
  },
  {
    "path": "lib/features/log/data/log_repository.dart",
    "content": "import 'package:flutter/foundation.dart';\nimport 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/utils/exception_handler.dart';\nimport 'package:hiddify/features/log/data/log_parser.dart';\nimport 'package:hiddify/features/log/data/log_path_resolver.dart';\nimport 'package:hiddify/features/log/model/log_entity.dart';\nimport 'package:hiddify/features/log/model/log_failure.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\n\nabstract interface class LogRepository {\n  TaskEither<LogFailure, Unit> init();\n  Stream<Either<LogFailure, List<LogEntity>>> watchLogs();\n  TaskEither<LogFailure, Unit> clearLogs();\n}\n\nclass LogRepositoryImpl with ExceptionHandler, InfraLogger implements LogRepository {\n  LogRepositoryImpl({required this.singbox, required this.logPathResolver});\n\n  final HiddifyCoreService singbox;\n  final LogPathResolver logPathResolver;\n\n  @override\n  TaskEither<LogFailure, Unit> init() {\n    return exceptionHandler(() async {\n      if (!kIsWeb) {\n        if (!await logPathResolver.directory.exists()) {\n          await logPathResolver.directory.create(recursive: true);\n        }\n        if (await logPathResolver.coreFile().exists()) {\n          await logPathResolver.coreFile().writeAsString(\"\");\n        } else {\n          await logPathResolver.coreFile().create(recursive: true);\n        }\n        if (await logPathResolver.appFile().exists()) {\n          await logPathResolver.appFile().writeAsString(\"\");\n        } else {\n          await logPathResolver.appFile().create(recursive: true);\n        }\n      }\n      return right(unit);\n    }, LogUnexpectedFailure.new);\n  }\n\n  @override\n  Stream<Either<LogFailure, List<LogEntity>>> watchLogs() {\n    return singbox\n        .watchLogs(logPathResolver.coreFile().path)\n        .map((event) => event.map(LogParser.parseLogProto).toList())\n        .handleExceptions((error, stackTrace) {\n          loggy.warning(\"error watching logs\", error, stackTrace);\n          return LogFailure.unexpected(error, stackTrace);\n        });\n  }\n\n  @override\n  TaskEither<LogFailure, Unit> clearLogs() {\n    return exceptionHandler(() => singbox.clearLogs().mapLeft(LogFailure.unexpected).run(), LogFailure.unexpected);\n  }\n}\n"
  },
  {
    "path": "lib/features/log/model/log_entity.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/features/log/model/log_level.dart';\n\npart 'log_entity.freezed.dart';\n\n@freezed\nclass LogEntity with _$LogEntity {\n  const factory LogEntity({LogLevel? level, DateTime? time, required String message}) = _LogEntity;\n}\n"
  },
  {
    "path": "lib/features/log/model/log_failure.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\n\npart 'log_failure.freezed.dart';\n\n@freezed\nsealed class LogFailure with _$LogFailure, Failure {\n  const LogFailure._();\n\n  @With<UnexpectedFailure>()\n  const factory LogFailure.unexpected([Object? error, StackTrace? stackTrace]) = LogUnexpectedFailure;\n\n  @override\n  ({String type, String? message}) present(TranslationsEn t) {\n    return switch (this) {\n      LogUnexpectedFailure() => (type: t.errors.unexpected, message: null),\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/log/model/log_level.dart",
    "content": "import 'package:dart_mappable/dart_mappable.dart';\nimport 'package:dartx/dartx.dart';\nimport 'package:flutter/material.dart';\n\npart 'log_level.mapper.dart';\n\n@MappableEnum()\nenum LogLevel {\n  trace,\n  debug,\n  info,\n  warn,\n  error,\n  fatal,\n  panic;\n\n  /// [LogLevel] selectable by user as preference\n  static List<LogLevel> get choices => values.takeFirst(4);\n\n  Color? get color => switch (this) {\n    trace => Colors.lightBlueAccent,\n    debug => Colors.grey,\n    info => Colors.lightGreen,\n    warn => Colors.orange,\n    error => Colors.redAccent,\n    fatal => Colors.red,\n    panic => Colors.red,\n  };\n}\n"
  },
  {
    "path": "lib/features/log/overview/logs_overview_notifier.dart",
    "content": "import 'dart:async';\n\nimport 'package:hiddify/features/log/data/log_data_providers.dart';\nimport 'package:hiddify/features/log/model/log_entity.dart';\nimport 'package:hiddify/features/log/model/log_level.dart';\nimport 'package:hiddify/features/log/overview/logs_overview_state.dart';\nimport 'package:hiddify/hiddifycore/init_signal.dart';\nimport 'package:hiddify/utils/riverpod_utils.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:rxdart/rxdart.dart';\n\npart 'logs_overview_notifier.g.dart';\n\n@riverpod\nclass LogsOverviewNotifier extends _$LogsOverviewNotifier with AppLogger {\n  @override\n  LogsOverviewState build() {\n    ref.disposeDelay(const Duration(seconds: 20));\n    state = const LogsOverviewState();\n    ref.onDispose(() {\n      loggy.debug(\"disposing\");\n      _listener?.cancel();\n      _listener = null;\n    });\n    ref.onCancel(() {\n      if (_listener?.isPaused != true) {\n        loggy.debug(\"pausing\");\n        _listener?.pause();\n      }\n    });\n    ref.onResume(() {\n      if (!state.paused && (_listener?.isPaused ?? false)) {\n        loggy.debug(\"resuming\");\n        _listener?.resume();\n      }\n    });\n\n    _addListeners();\n    return const LogsOverviewState();\n  }\n\n  StreamSubscription? _listener;\n\n  Future<void> _addListeners() async {\n    loggy.debug(\"adding listeners\");\n    ref.watch(coreRestartSignalProvider);\n    await _listener?.cancel();\n    _listener = ref\n        .read(logRepositoryProvider)\n        .requireValue\n        .watchLogs()\n        .throttle((_) => Stream.value(_listener?.isPaused ?? false), leading: false, trailing: true)\n        .throttleTime(const Duration(milliseconds: 250), leading: false, trailing: true)\n        .asyncMap((event) async {\n          await event.fold(\n            (f) {\n              _logs = [];\n              state = state.copyWith(logs: AsyncError(f, StackTrace.current));\n            },\n            (a) async {\n              _logs = a.reversed;\n              state = state.copyWith(logs: AsyncData(await _computeLogs()));\n            },\n          );\n        })\n        .listen((event) {});\n  }\n\n  Iterable<LogEntity> _logs = [];\n  final _debouncer = CallbackDebouncer(const Duration(milliseconds: 200));\n  LogLevel? _levelFilter;\n  String _filter = \"\";\n\n  Future<List<LogEntity>> _computeLogs() async {\n    if (_levelFilter == null && _filter.isEmpty) return _logs.toList();\n    return _logs.where((e) {\n      return (_filter.isEmpty || e.message.contains(_filter)) &&\n          (_levelFilter == null || e.level == null || e.level!.index >= _levelFilter!.index);\n    }).toList();\n  }\n\n  void pause() {\n    loggy.debug(\"pausing\");\n    _listener?.pause();\n    state = state.copyWith(paused: true);\n  }\n\n  void resume() {\n    loggy.debug(\"resuming\");\n    _listener?.resume();\n    state = state.copyWith(paused: false);\n  }\n\n  Future<void> clear() async {\n    loggy.debug(\"clearing\");\n    await ref\n        .read(logRepositoryProvider)\n        .requireValue\n        .clearLogs()\n        .match(\n          (l) {\n            loggy.warning(\"error clearing logs\", l);\n          },\n          (_) {\n            _logs = [];\n            state = state.copyWith(logs: const AsyncData([]));\n          },\n        )\n        .run();\n  }\n\n  void filterMessage(String? filter) {\n    _filter = filter ?? '';\n    _debouncer(() async {\n      if (state.logs case AsyncData()) {\n        state = state.copyWith(filter: _filter, logs: AsyncData(await _computeLogs()));\n      }\n    });\n  }\n\n  Future<void> filterLevel(LogLevel? level) async {\n    _levelFilter = level;\n    if (state.logs case AsyncData()) {\n      state = state.copyWith(levelFilter: _levelFilter, logs: AsyncData(await _computeLogs()));\n    }\n  }\n}\n"
  },
  {
    "path": "lib/features/log/overview/logs_overview_state.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/features/log/model/log_entity.dart';\nimport 'package:hiddify/features/log/model/log_level.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'logs_overview_state.freezed.dart';\n\n@freezed\nclass LogsOverviewState with _$LogsOverviewState {\n  const LogsOverviewState._();\n\n  const factory LogsOverviewState({\n    @Default(AsyncLoading()) AsyncValue<List<LogEntity>> logs,\n    @Default(false) bool paused,\n    @Default(\"\") String filter,\n    LogLevel? levelFilter,\n  }) = _LogsOverviewState;\n}\n"
  },
  {
    "path": "lib/features/log/overview/logs_page.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:fpdart/fpdart.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/widget/adaptive_icon.dart';\nimport 'package:hiddify/features/log/data/log_data_providers.dart';\nimport 'package:hiddify/features/log/model/log_level.dart';\nimport 'package:hiddify/features/log/overview/logs_overview_notifier.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:sliver_tools/sliver_tools.dart';\n\nclass LogsPage extends HookConsumerWidget with PresLogger {\n  const LogsPage({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final state = ref.watch(logsOverviewNotifierProvider);\n    final notifier = ref.watch(logsOverviewNotifierProvider.notifier);\n\n    final debug = ref.watch(debugModeNotifierProvider);\n    final pathResolver = ref.watch(logPathResolverProvider);\n\n    final filterController = useTextEditingController(text: state.filter);\n\n    final List<PopupMenuEntry> popupButtons = debug || PlatformUtils.isDesktop\n        ? [\n            PopupMenuItem(\n              child: Text(t.pages.logs.shareCoreLogs),\n              onTap: () async {\n                await UriUtils.tryShareOrLaunchFile(\n                  Uri.parse(pathResolver.coreFile().path),\n                  fileOrDir: pathResolver.directory.uri,\n                );\n              },\n            ),\n            PopupMenuItem(\n              child: Text(t.pages.logs.shareAppLogs),\n              onTap: () async {\n                await UriUtils.tryShareOrLaunchFile(\n                  Uri.parse(pathResolver.appFile().path),\n                  fileOrDir: pathResolver.directory.uri,\n                );\n              },\n            ),\n          ]\n        : [];\n\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(t.pages.logs.title),\n        actions: [\n          if (state.paused)\n            IconButton(\n              onPressed: notifier.resume,\n              icon: const Icon(FluentIcons.play_20_regular),\n              tooltip: t.common.resume,\n              iconSize: 20,\n            )\n          else\n            IconButton(\n              onPressed: notifier.pause,\n              icon: const Icon(FluentIcons.pause_20_regular),\n              tooltip: t.common.pause,\n              iconSize: 20,\n            ),\n          IconButton(\n            onPressed: notifier.clear,\n            icon: const Icon(FluentIcons.delete_lines_20_regular),\n            tooltip: t.common.clear,\n            iconSize: 20,\n          ),\n          if (popupButtons.isNotEmpty)\n            PopupMenuButton(\n              icon: Icon(AdaptiveIcon(context).more),\n              itemBuilder: (context) {\n                return popupButtons;\n              },\n            ),\n          const Gap(8),\n        ],\n      ),\n      body: NestedScrollView(\n        headerSliverBuilder: (context, innerBoxIsScrolled) {\n          return <Widget>[\n            SliverOverlapAbsorber(\n              handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),\n              sliver: MultiSliver(\n                children: [\n                  // NestedAppBar(\n                  //   forceElevated: innerBoxIsScrolled,\n                  // ),\n                  SliverPinnedHeader(\n                    child: DecoratedBox(\n                      decoration: BoxDecoration(color: Theme.of(context).colorScheme.surface),\n                      child: Padding(\n                        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),\n                        child: Row(\n                          children: [\n                            Flexible(\n                              child: TextFormField(\n                                controller: filterController,\n                                onChanged: notifier.filterMessage,\n                                decoration: InputDecoration(isDense: true, hintText: t.common.filter),\n                              ),\n                            ),\n                            const Gap(16),\n                            DropdownButton<Option<LogLevel>>(\n                              value: optionOf(state.levelFilter),\n                              onChanged: (v) {\n                                if (v == null) return;\n                                notifier.filterLevel(v.toNullable());\n                              },\n                              padding: const EdgeInsets.symmetric(horizontal: 8),\n                              borderRadius: BorderRadius.circular(4),\n                              items: [\n                                DropdownMenuItem(value: none(), child: Text(t.common.all)),\n                                ...LogLevel.choices.map((e) => DropdownMenuItem(value: some(e), child: Text(e.name))),\n                              ],\n                            ),\n                          ],\n                        ),\n                      ),\n                    ),\n                  ),\n                ],\n              ),\n            ),\n          ];\n        },\n        body: Builder(\n          builder: (context) {\n            return CustomScrollView(\n              primary: false,\n              reverse: true,\n              slivers: <Widget>[\n                switch (state.logs) {\n                  AsyncData(value: final logs) => SliverList.builder(\n                    itemCount: logs.length,\n                    itemBuilder: (context, index) {\n                      final log = logs[index];\n                      return Column(\n                        mainAxisSize: MainAxisSize.min,\n                        crossAxisAlignment: CrossAxisAlignment.start,\n                        children: [\n                          Padding(\n                            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),\n                            child: Column(\n                              crossAxisAlignment: CrossAxisAlignment.start,\n                              children: [\n                                if (log.level != null)\n                                  Row(\n                                    mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                                    children: [\n                                      Text(\n                                        log.level!.name.toUpperCase(),\n                                        style: Theme.of(\n                                          context,\n                                        ).textTheme.labelMedium?.copyWith(color: log.level!.color),\n                                      ),\n                                      if (log.time != null)\n                                        Text(log.time!.toString(), style: Theme.of(context).textTheme.labelSmall),\n                                    ],\n                                  ),\n                                Text(extractMessage(log.message), style: Theme.of(context).textTheme.bodySmall),\n                              ],\n                            ),\n                          ),\n                          if (index != 0) const Divider(indent: 16, endIndent: 16, height: 4),\n                        ],\n                      );\n                    },\n                  ),\n                  AsyncError(:final error) => SliverErrorBodyPlaceholder(t.presentShortError(error)),\n                  _ => const SliverLoadingBodyPlaceholder(),\n                },\n                SliverOverlapInjector(handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context)),\n              ],\n            );\n          },\n        ),\n      ),\n    );\n  }\n}\n\nString extractMessage(String message) {\n  final parts = message.split(' ');\n  return parts.length <= 2 ? parts.last : parts.sublist(2).join(' ');\n}\n"
  },
  {
    "path": "lib/features/per_app_proxy/data/app_proxy_data_source.dart",
    "content": "import 'package:drift/drift.dart';\nimport 'package:hiddify/core/db/db.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_backup.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_mode.dart';\nimport 'package:hiddify/features/per_app_proxy/model/pkg_flag.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\n\npart 'app_proxy_data_source.g.dart';\n\nabstract interface class AppProxyDataSource {\n  Future<void> updatePkg({required String pkg, required AppProxyMode mode});\n  Stream<List<AppProxyEntry>> watchAll({required AppProxyMode mode});\n  Stream<List<AppProxyEntry>> watchFilterForDisplay({required Set<String> phonePkgs, required AppProxyMode mode});\n  Stream<List<String>> watchActivePackages({required Set<String> phonePkgs, required AppProxyMode mode});\n  Future<List<String>> getPkgsByFlag({required PkgFlag flag, required AppProxyMode mode});\n  Future<void> importPkgs({required PerAppProxyBackup backup});\n  Future<void> applyAutoSelection({required Set<String> autoList, required AppProxyMode mode});\n  Future<void> clearAutoSelected({required AppProxyMode mode});\n  Future<void> revertForceDeselection({required AppProxyMode mode});\n  Future<int> clearAll({required AppProxyMode mode});\n}\n\n@DriftAccessor(tables: [AppProxyEntries])\nclass AppProxyDao extends DatabaseAccessor<Db> with _$AppProxyDaoMixin, InfraLogger implements AppProxyDataSource {\n  AppProxyDao(super.db);\n\n  @override\n  Future<void> updatePkg({required String pkg, required AppProxyMode mode}) {\n    return transaction(() async {\n      final entry = await (select(\n        appProxyEntries,\n      )..where((tbl) => tbl.mode.equalsValue(mode) & tbl.pkgName.equals(pkg))).getSingleOrNull();\n\n      if (entry == null) {\n        await into(\n          appProxyEntries,\n        ).insert(AppProxyEntriesCompanion.insert(mode: mode, pkgName: pkg, flags: Value(PkgFlag.userSelection.add(0))));\n        return;\n      }\n\n      final flag = entry.flags;\n      final isAutoSelection = PkgFlag.autoSelection.check(flag);\n\n      if (!isAutoSelection) {\n        await (delete(appProxyEntries)..where((tbl) => tbl.mode.equalsValue(mode) & tbl.pkgName.equals(pkg))).go();\n        return;\n      }\n\n      int newFlag;\n      if (PkgFlag.forceDeselection.check(flag)) {\n        newFlag = PkgFlag.forceDeselection.remove(PkgFlag.userSelection.remove(flag));\n      } else if (PkgFlag.userSelection.check(flag)) {\n        newFlag = PkgFlag.forceDeselection.add(flag);\n      } else {\n        newFlag = PkgFlag.userSelection.add(flag);\n      }\n\n      await (update(appProxyEntries)..where((tbl) => tbl.mode.equalsValue(mode) & tbl.pkgName.equals(pkg))).write(\n        AppProxyEntriesCompanion(flags: Value(newFlag)),\n      );\n    });\n  }\n\n  @override\n  Stream<List<AppProxyEntry>> watchAll({required AppProxyMode mode}) {\n    final query = select(appProxyEntries)..where((tbl) => tbl.mode.equalsValue(mode));\n    return query.watch();\n  }\n\n  @override\n  Stream<List<AppProxyEntry>> watchFilterForDisplay({required Set<String> phonePkgs, required AppProxyMode mode}) {\n    if (phonePkgs.isEmpty) return Stream.value([]);\n\n    return (select(appProxyEntries)..where((tbl) {\n          final modeFilter = tbl.mode.equalsValue(mode);\n          final packageFilter = tbl.pkgName.isIn(phonePkgs);\n          return modeFilter & packageFilter;\n        }))\n        .watch();\n  }\n\n  @override\n  Stream<List<String>> watchActivePackages({required Set<String> phonePkgs, required AppProxyMode mode}) {\n    if (phonePkgs.isEmpty) return Stream.value([]);\n\n    final query = selectOnly(appProxyEntries)..addColumns([appProxyEntries.pkgName]);\n\n    final modeFilter = appProxyEntries.mode.equalsValue(mode);\n    final packageFilter = appProxyEntries.pkgName.isIn(phonePkgs);\n    final isForceDeselectionSet = appProxyEntries.flags\n        .bitwiseAnd(Constant(PkgFlag.forceDeselection.value))\n        .equals(PkgFlag.forceDeselection.value);\n\n    final combinedFilter = modeFilter & packageFilter & isForceDeselectionSet.not();\n\n    query.where(combinedFilter);\n\n    return query.watch().map((rows) {\n      return rows.map((row) => row.read(appProxyEntries.pkgName)!).toList();\n    });\n  }\n\n  @override\n  Future<List<String>> getPkgsByFlag({required PkgFlag flag, required AppProxyMode mode}) {\n    final query = selectOnly(appProxyEntries)..addColumns([appProxyEntries.pkgName]);\n    final filter =\n        appProxyEntries.mode.equalsValue(mode) &\n        (appProxyEntries.flags.bitwiseAnd(Constant(flag.value)).equals(flag.value));\n\n    query.where(filter);\n\n    return query.map((row) => row.read(appProxyEntries.pkgName)!).get();\n  }\n\n  @override\n  Future<void> importPkgs({required PerAppProxyBackup backup}) {\n    return transaction(() async {\n      await (delete(appProxyEntries)..where((tbl) => tbl.flags.equals(0))).go();\n\n      await db.batch((b) {\n        b\n          ..update(\n            appProxyEntries,\n            AppProxyEntriesCompanion.custom(\n              flags: appProxyEntries.flags\n                ..bitwiseAnd(Constant(~PkgFlag.userSelection.value))\n                ..bitwiseAnd(Constant(~PkgFlag.forceDeselection.value)),\n            ),\n          )\n          ..deleteWhere(appProxyEntries, (tbl) => tbl.flags.equals(0))\n          ..insertAll(\n            db.appProxyEntries,\n            <AppProxyEntriesCompanion>[\n              ...backup.include.selected.map(\n                (pkg) => AppProxyEntriesCompanion.insert(\n                  mode: AppProxyMode.include,\n                  pkgName: pkg,\n                  flags: Value(PkgFlag.userSelection.add(0)),\n                ),\n              ),\n              ...backup.include.deselected.map(\n                (pkg) => AppProxyEntriesCompanion.insert(\n                  mode: AppProxyMode.include,\n                  pkgName: pkg,\n                  flags: Value(PkgFlag.forceDeselection.add(0)),\n                ),\n              ),\n              ...backup.exclude.selected.map(\n                (pkg) => AppProxyEntriesCompanion.insert(\n                  mode: AppProxyMode.exclude,\n                  pkgName: pkg,\n                  flags: Value(PkgFlag.userSelection.add(0)),\n                ),\n              ),\n              ...backup.exclude.deselected.map(\n                (pkg) => AppProxyEntriesCompanion.insert(\n                  mode: AppProxyMode.exclude,\n                  pkgName: pkg,\n                  flags: Value(PkgFlag.forceDeselection.add(0)),\n                ),\n              ),\n            ],\n            onConflict: DoUpdate.withExcluded((AppProxyEntries old, AppProxyEntries e) {\n              return AppProxyEntriesCompanion.custom(flags: old.flags.bitwiseOr(e.flags));\n            }),\n          );\n      });\n    });\n  }\n\n  @override\n  Future<void> applyAutoSelection({required Set<String> autoList, required AppProxyMode mode}) {\n    return transaction(() async {\n      // removing all items that have only auto selection\n      await (delete(\n        appProxyEntries,\n      )..where((tbl) => tbl.mode.equalsValue(mode) & tbl.flags.equals(PkgFlag.autoSelection.value))).go();\n      // removing auto selection flag from items\n      final entriesToUpdate = await (db.select(db.appProxyEntries)..where((tbl) => tbl.mode.equalsValue(mode))).get();\n      if (entriesToUpdate.isNotEmpty) {\n        final updatedCompanions = entriesToUpdate.map((entry) {\n          return entry.copyWith(flags: PkgFlag.autoSelection.remove(entry.flags)).toCompanion(false);\n        }).toList();\n        await db.batch((b) {\n          b.replaceAll(db.appProxyEntries, updatedCompanions);\n        });\n      }\n      // adding auto selected\n      if (autoList.isNotEmpty) {\n        await db.batch((b) {\n          b.insertAll(\n            db.appProxyEntries,\n            autoList.map(\n              (pkg) =>\n                  AppProxyEntriesCompanion.insert(mode: mode, pkgName: pkg, flags: Value(PkgFlag.autoSelection.add(0))),\n            ),\n            onConflict: DoUpdate((AppProxyEntries old) {\n              return AppProxyEntriesCompanion.custom(flags: old.flags.bitwiseOr(Constant(PkgFlag.autoSelection.value)));\n            }),\n          );\n        });\n      }\n    });\n  }\n\n  @override\n  Future<void> clearAutoSelected({required AppProxyMode mode}) {\n    return transaction(() async {\n      // removing all items that have only auto selection\n      await (delete(\n        appProxyEntries,\n      )..where((tbl) => tbl.mode.equalsValue(mode) & (appProxyEntries.flags.equals(PkgFlag.autoSelection.value)))).go();\n      // removing auto selection flag from items\n      await (update(appProxyEntries)..where((tbl) => tbl.mode.equalsValue(mode))).write(\n        AppProxyEntriesCompanion.custom(\n          flags: appProxyEntries.flags.bitwiseAnd(Constant(~PkgFlag.autoSelection.value)),\n        ),\n      );\n    });\n  }\n\n  @override\n  Future<void> revertForceDeselection({required AppProxyMode mode}) {\n    return transaction(() async {\n      // remove forceDeselection flag from flags\n      await (update(appProxyEntries)..where((tbl) => tbl.mode.equalsValue(mode))).write(\n        AppProxyEntriesCompanion.custom(\n          flags: appProxyEntries.flags.bitwiseAnd(Constant(~PkgFlag.forceDeselection.value)),\n        ),\n      );\n      // romve extra items\n      await (delete(appProxyEntries)..where((tbl) => tbl.mode.equalsValue(mode) & tbl.flags.equals(0))).go();\n    });\n  }\n\n  @override\n  Future<int> clearAll({required AppProxyMode mode}) {\n    return (delete(appProxyEntries)..where((tbl) => tbl.mode.equalsValue(mode))).go();\n  }\n}\n"
  },
  {
    "path": "lib/features/per_app_proxy/data/auto_selection_repository.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:hiddify/core/http_client/dio_http_client.dart';\nimport 'package:hiddify/core/http_client/http_client_provider.dart';\nimport 'package:hiddify/core/model/region.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_mode.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nenum AutoSelectionResult {\n  success,\n  failure,\n  notFound;\n\n  bool isSuccess() => this == success;\n  bool isFailure() => this == failure;\n  bool isNotFound() => this == notFound;\n}\n\nabstract interface class AutoSelectionRepository {\n  Future<(Set<String>?, AutoSelectionResult)> getByAppProxyMode({AppProxyMode? mode, Region? region});\n  Future<(Set<String>?, AutoSelectionResult)> getInclude({Region? region});\n  Future<(Set<String>?, AutoSelectionResult)> getExclude({Region? region});\n}\n\nclass AutoSelectionRepositoryImpl with AppLogger implements AutoSelectionRepository {\n  AutoSelectionRepositoryImpl({required Ref ref}) : _ref = ref;\n  final Ref _ref;\n  static const _baseUrl = 'https://raw.githubusercontent.com/hiddify/Android-GFW-Apps/refs/heads/master/';\n\n  @override\n  Future<(Set<String>?, AutoSelectionResult)> getByAppProxyMode({AppProxyMode? mode, Region? region}) async =>\n      await _makeRequest(mode: mode ?? _getMode(), region: region ?? _getRegion());\n\n  @override\n  Future<(Set<String>?, AutoSelectionResult)> getExclude({Region? region}) async =>\n      await _makeRequest(mode: AppProxyMode.exclude, region: region ?? _getRegion());\n\n  @override\n  Future<(Set<String>?, AutoSelectionResult)> getInclude({Region? region}) async =>\n      await _makeRequest(mode: AppProxyMode.include, region: region ?? _getRegion());\n\n  Future<(Set<String>?, AutoSelectionResult)> _makeRequest({required AppProxyMode mode, Region? region}) async {\n    try {\n      final rs = await _getHttp().get(_genUrl(mode, region ?? _getRegion()));\n      if (rs.statusCode == 200) {\n        return (_parseToListOfString(rs.data), AutoSelectionResult.success);\n      }\n      loggy.error(\"Auto selection failed. status code : ${rs.statusCode}\");\n      return (null, AutoSelectionResult.failure);\n    } on DioException catch (e, st) {\n      if (e.response?.statusCode == 404) {\n        loggy.error(\"Auto selection region not found. region : ${region?.name ?? _getRegion().name}\", e, st);\n        return (null, AutoSelectionResult.notFound);\n      } else {\n        loggy.error(\"Failed to fetch auto selection\", e, st);\n        return (null, AutoSelectionResult.failure);\n      }\n    } catch (e, st) {\n      loggy.error(\"Failed to fetch auto selection with unexpected error\", e, st);\n      return (null, AutoSelectionResult.failure);\n    }\n  }\n\n  String _genUrl(AppProxyMode mode, Region region) => switch (mode) {\n    AppProxyMode.include => '${_baseUrl}proxy_${region.name}',\n    AppProxyMode.exclude => '${_baseUrl}direct_${region.name}',\n  };\n\n  Set<String> _parseToListOfString(dynamic data) =>\n      data.toString().split('\\n').map((e) => e.trim()).where((element) => element.isNotEmpty).toSet();\n\n  AppProxyMode _getMode() => _ref.read(Preferences.perAppProxyMode).toAppProxy()!;\n\n  Region _getRegion() => _ref.read(ConfigOptions.region);\n\n  DioHttpClient _getHttp() => _ref.read(httpClientProvider);\n}\n"
  },
  {
    "path": "lib/features/per_app_proxy/data/auto_selection_repository_provider.dart",
    "content": "import 'package:hiddify/features/per_app_proxy/data/auto_selection_repository.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'auto_selection_repository_provider.g.dart';\n\n@riverpod\nAutoSelectionRepository autoSelectionRepo(Ref ref) => AutoSelectionRepositoryImpl(ref: ref);\n"
  },
  {
    "path": "lib/features/per_app_proxy/data/selected_data_provider.dart",
    "content": "import 'package:hiddify/core/db/provider/db_providers.dart';\nimport 'package:hiddify/features/per_app_proxy/data/app_proxy_data_source.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'selected_data_provider.g.dart';\n\n@riverpod\nAppProxyDataSource appProxyDataSource(Ref ref) => AppProxyDao(ref.watch(dbProvider));\n"
  },
  {
    "path": "lib/features/per_app_proxy/model/app_package_info.dart",
    "content": "import 'dart:typed_data';\n\nclass AppPackageInfo {\n  const AppPackageInfo({required this.packageName, required this.name, required this.icon});\n  final String packageName;\n  final String name;\n  final Uint8List? icon;\n}\n"
  },
  {
    "path": "lib/features/per_app_proxy/model/per_app_proxy_backup.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\n\npart 'per_app_proxy_backup.freezed.dart';\npart 'per_app_proxy_backup.g.dart';\n\n@freezed\nabstract class PerAppProxyBackup with _$PerAppProxyBackup {\n  const factory PerAppProxyBackup({\n    @Default(PerAppProxyBackupMode()) PerAppProxyBackupMode include,\n    @Default(PerAppProxyBackupMode()) PerAppProxyBackupMode exclude,\n  }) = _PerAppProxyBackup;\n\n  factory PerAppProxyBackup.fromJson(Map<String, Object?> json) => _$PerAppProxyBackupFromJson(json);\n}\n\n@freezed\nabstract class PerAppProxyBackupMode with _$PerAppProxyBackupMode {\n  const factory PerAppProxyBackupMode({@Default([]) List<String> selected, @Default([]) List<String> deselected}) =\n      _PerAppProxyBackupMode;\n\n  factory PerAppProxyBackupMode.fromJson(Map<String, Object?> json) => _$PerAppProxyBackupModeFromJson(json);\n}\n"
  },
  {
    "path": "lib/features/per_app_proxy/model/per_app_proxy_mode.dart",
    "content": "import 'package:hiddify/core/localization/translations.dart';\n\nenum PerAppProxyMode {\n  off,\n  include,\n  exclude;\n\n  bool get enabled => this != off;\n\n  ({String title, String message}) present(TranslationsEn t) => switch (this) {\n    off => (\n      title: t.pages.settings.routing.perAppProxy.modes.all,\n      message: t.pages.settings.routing.perAppProxy.modes.allMsg,\n    ),\n    include => (\n      title: t.pages.settings.routing.perAppProxy.modes.proxy,\n      message: t.pages.settings.routing.perAppProxy.modes.proxyMsg,\n    ),\n    exclude => (\n      title: t.pages.settings.routing.perAppProxy.modes.bypass,\n      message: t.pages.settings.routing.perAppProxy.modes.bypassMsg,\n    ),\n  };\n\n  AppProxyMode? toAppProxy() => switch (this) {\n    PerAppProxyMode.off => null,\n    PerAppProxyMode.include => AppProxyMode.include,\n    PerAppProxyMode.exclude => AppProxyMode.exclude,\n  };\n}\n\nenum AppProxyMode {\n  include,\n  exclude;\n\n  PerAppProxyMode toPerAppProxy() => switch (this) {\n    AppProxyMode.include => PerAppProxyMode.include,\n    AppProxyMode.exclude => PerAppProxyMode.exclude,\n  };\n\n  ({String title, String message}) present(Translations t) => switch (this) {\n    include => (\n      title: t.pages.settings.routing.perAppProxy.modes.proxy,\n      message: t.pages.settings.routing.perAppProxy.modes.proxyMsg,\n    ),\n    exclude => (\n      title: t.pages.settings.routing.perAppProxy.modes.bypass,\n      message: t.pages.settings.routing.perAppProxy.modes.bypassMsg,\n    ),\n  };\n}\n"
  },
  {
    "path": "lib/features/per_app_proxy/model/pkg_flag.dart",
    "content": "enum PkgFlag {\n  userSelection(1 << 0),\n  forceDeselection(1 << 1),\n  autoSelection(1 << 2);\n\n  final int value;\n  const PkgFlag(this.value);\n\n  bool check(int value) => (value & this.value) == this.value;\n\n  int add(int value) {\n    int nValue = value;\n    if (this == userSelection) {\n      nValue = forceDeselection.remove(nValue);\n    } else if (this == forceDeselection) {\n      nValue = userSelection.remove(nValue);\n    }\n    return nValue | this.value;\n  }\n\n  int remove(int value) => value & ~this.value;\n\n  int toggle(int value) => value ^ this.value;\n\n  static bool? checkboxValue(int flag) => switch (flag) {\n    _ when forceDeselection.check(flag) => false,\n    _ when autoSelection.check(flag) && !userSelection.check(flag) => null,\n    _ when userSelection.check(flag) => true,\n    _ => null,\n  };\n}\n"
  },
  {
    "path": "lib/features/per_app_proxy/overview/per_app_proxy_loading_notifier.dart",
    "content": "import 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'per_app_proxy_loading_notifier.g.dart';\n\n@Riverpod()\nclass AppProxyLoading extends _$AppProxyLoading {\n  @override\n  bool build() => false;\n\n  Future<T?> doAsync<T>(Future<T> Function() operation) async {\n    state = true;\n    final T? result = await operation();\n    state = false;\n    return result;\n  }\n}\n"
  },
  {
    "path": "lib/features/per_app_proxy/overview/per_app_proxy_notifier.dart",
    "content": "import 'dart:async';\nimport 'dart:convert';\nimport 'dart:io';\n\nimport 'package:dartx/dartx_io.dart';\nimport 'package:file_picker/file_picker.dart';\nimport 'package:flutter/services.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/region.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/per_app_proxy/data/auto_selection_repository.dart';\nimport 'package:hiddify/features/per_app_proxy/data/auto_selection_repository_provider.dart';\nimport 'package:hiddify/features/per_app_proxy/data/selected_data_provider.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_backup.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_mode.dart';\nimport 'package:hiddify/features/per_app_proxy/model/pkg_flag.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:installed_apps/index.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'per_app_proxy_notifier.g.dart';\n\n@riverpod\nclass PerAppProxy extends _$PerAppProxy with AppLogger {\n  late final AppProxyMode? _mode;\n\n  @override\n  Stream<Map<String, int>> build(AppProxyMode? mode) {\n    _mode = mode;\n    if (_mode == null) return Stream.value({});\n    final appsInfo = InstalledApps.getInstalledApps(false);\n    return Stream.fromFuture(appsInfo).asyncExpand((appsInfo) {\n      final phonePkgs = appsInfo.map((e) => e.packageName).toSet();\n      return ref.watch(appProxyDataSourceProvider).watchFilterForDisplay(phonePkgs: phonePkgs, mode: _mode).map((\n        entryList,\n      ) {\n        return {for (final entry in entryList) entry.pkgName: entry.flags};\n      });\n    });\n  }\n\n  Future<void> updatePkg(String pkg) async {\n    loggy.info('Updationg $pkg status');\n    await ref.read(appProxyDataSourceProvider).updatePkg(pkg: pkg, mode: _mode!);\n  }\n\n  Future<bool> applyAutoSelection() async {\n    loggy.info('Performming auto selection');\n    final t = ref.watch(translationsProvider).requireValue;\n    final region = ref.watch(ConfigOptions.region);\n    final rs = await ref.watch(autoSelectionRepoProvider).getByAppProxyMode(mode: _mode);\n    switch (rs.$2) {\n      case AutoSelectionResult.success:\n        final autoList = rs.$1!;\n        await ref.read(appProxyDataSourceProvider).applyAutoSelection(autoList: autoList, mode: _mode!);\n        await ref.read(Preferences.autoAppsSelectionRegion.notifier).update(region);\n        await ref.read(Preferences.autoAppsSelectionLastUpdate.notifier).update(DateTime.now());\n        return true;\n      case AutoSelectionResult.failure:\n        ref\n            .read(inAppNotificationControllerProvider)\n            .showErrorToast(t.pages.settings.routing.perAppProxy.autoSelection.toast.failure);\n        return false;\n      case AutoSelectionResult.notFound:\n        ref\n            .read(inAppNotificationControllerProvider)\n            .showInfoToast(\n              t.pages.settings.routing.perAppProxy.autoSelection.toast.regionNotFound(\n                region: ref.watch(ConfigOptions.region).name,\n              ),\n              duration: const Duration(seconds: 5),\n            );\n        return false;\n    }\n  }\n\n  Future<void> revertForceDeselection() async {\n    loggy.info('Reverting force deselection');\n    await ref.read(appProxyDataSourceProvider).revertForceDeselection(mode: _mode!);\n  }\n\n  Future<void> clearAutoSelected() async {\n    loggy.info('Clearing auto selected');\n    await ref.read(appProxyDataSourceProvider).clearAutoSelected(mode: _mode!);\n    await ref.watch(Preferences.autoAppsSelectionRegion.notifier).update(null);\n    await ref.read(Preferences.autoAppsSelectionLastUpdate.notifier).update(null);\n  }\n\n  Future<void> clearAll() async {\n    loggy.info('Clearing all items');\n    await ref.read(appProxyDataSourceProvider).clearAll(mode: _mode!);\n    await ref.watch(Preferences.autoAppsSelectionRegion.notifier).update(null);\n  }\n\n  Future<bool> importClipboard() async {\n    final t = ref.read(translationsProvider).requireValue;\n    try {\n      final input = await Clipboard.getData(Clipboard.kTextPlain).then((value) => value?.text);\n      await _importJson(input!);\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.import.success);\n      return true;\n    } catch (e, st) {\n      loggy.warning(\"error importing from clipboard\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.import.failure);\n      return false;\n    }\n  }\n\n  Future<bool> importFile() async {\n    final t = ref.read(translationsProvider).requireValue;\n    try {\n      final result = await FilePicker.platform.pickFiles(type: FileType.custom, allowedExtensions: ['json']);\n      final file = File(result!.files.single.path!);\n      if (!await file.exists()) throw Exception('File does not exist: path = ${file.path}');\n      final bytes = await file.readAsBytes();\n      await _importJson(jsonDecode(utf8.decode(bytes)).toString());\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.import.success);\n      return true;\n    } catch (e, st) {\n      loggy.warning(\"error importing config options from json file\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.import.failure);\n      return false;\n    }\n  }\n\n  Future<bool> exportClipboard() async {\n    final t = ref.watch(translationsProvider).requireValue;\n    try {\n      final json = await _exportJson();\n      await Clipboard.setData(ClipboardData(text: json));\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.export.clipboard.success);\n      return true;\n    } on PlatformException {\n      ref\n          .read(inAppNotificationControllerProvider)\n          .showInfoToast(t.common.msg.export.clipboard.contentTooLarge, duration: const Duration(seconds: 5));\n      return false;\n    } catch (e, st) {\n      loggy.warning(\"error exporting to clipboard\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.export.clipboard.failure);\n      return false;\n    }\n  }\n\n  Future<bool> exportFile() async {\n    final t = ref.watch(translationsProvider).requireValue;\n    try {\n      final json = await _exportJson();\n      final bytes = utf8.encode(jsonEncode(json));\n      final outputFile = await FilePicker.platform.saveFile(\n        fileName: 'per-app proxy.json',\n        type: FileType.custom,\n        allowedExtensions: ['json'],\n        bytes: bytes,\n      );\n      if (outputFile == null) return false;\n      if (PlatformUtils.isDesktop) {\n        final file = File(outputFile);\n        if (file.extension != '.json') return false;\n        if (!await file.exists()) await file.parent.create(recursive: true);\n        await file.writeAsBytes(bytes);\n      }\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.export.file.success);\n      return true;\n    } catch (e, st) {\n      loggy.warning(\"error exporting config options to json file\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.export.file.failure);\n      return false;\n    }\n  }\n\n  Future<bool> shareOnGithub() async {\n    final t = ref.watch(translationsProvider).requireValue;\n    final region = ref.watch(ConfigOptions.region);\n    final mode = ref.watch(Preferences.perAppProxyMode).toAppProxy()!;\n    assert(region != Region.other);\n    final rs = await ref.read(autoSelectionRepoProvider).getByAppProxyMode(mode: mode, region: region);\n    if (rs.$2 != AutoSelectionResult.success) return false;\n    final autoList = rs.$1!;\n    final userSelected =\n        (await ref.read(appProxyDataSourceProvider).getPkgsByFlag(mode: mode, flag: PkgFlag.userSelection))\n          ..removeWhere((pkg) => autoList.contains(pkg));\n    final forceDeselected =\n        (await ref.read(appProxyDataSourceProvider).getPkgsByFlag(mode: mode, flag: PkgFlag.forceDeselection))\n          ..removeWhere((pkg) => !autoList.contains(pkg));\n\n    if (userSelected.isNotEmpty || forceDeselected.isNotEmpty) {\n      final agree = await ref\n          .read(dialogNotifierProvider.notifier)\n          .showConfirmation(\n            title: t.dialogs.confirmation.perAppProxy.shareOnGithub.title,\n            message: t.dialogs.confirmation.perAppProxy.shareOnGithub.msg,\n            positiveBtnTxt: t.common.kContinue,\n          );\n      if (agree != true) return false;\n      final title = '${region.name} | ${mode.present(t).title}';\n      var body = const JsonEncoder.withIndent(\n        '  ',\n      ).convert({'addedPkgs': userSelected.toList(), 'removedPkgs': forceDeselected.toList()});\n      body = '```\\n$body\\n```';\n      UriUtils.tryLaunch(Uri.parse('https://github.com/hiddify/Android-GFW-Apps/issues/new?title=$title&body=$body'));\n      return true;\n    } else {\n      ref\n          .read(inAppNotificationControllerProvider)\n          .showInfoToast(\n            t.pages.settings.routing.perAppProxy.autoSelection.toast.alreadyInAuto,\n            duration: const Duration(seconds: 5),\n          );\n      return false;\n    }\n  }\n\n  Future<void> _importJson(String input) async {\n    final backup = PerAppProxyBackup.fromJson((jsonDecode(input) as Map).cast());\n    await ref.read(appProxyDataSourceProvider).importPkgs(backup: backup);\n  }\n\n  Future<String> _exportJson() async {\n    final ds = ref.read(appProxyDataSourceProvider);\n    final backup = PerAppProxyBackup(\n      include: PerAppProxyBackupMode(\n        selected: await ds.getPkgsByFlag(mode: AppProxyMode.include, flag: PkgFlag.userSelection),\n        deselected: await ds.getPkgsByFlag(mode: AppProxyMode.include, flag: PkgFlag.forceDeselection),\n      ),\n      exclude: PerAppProxyBackupMode(\n        selected: await ds.getPkgsByFlag(mode: AppProxyMode.exclude, flag: PkgFlag.userSelection),\n        deselected: await ds.getPkgsByFlag(mode: AppProxyMode.exclude, flag: PkgFlag.forceDeselection),\n      ),\n    );\n    return const JsonEncoder.withIndent('  ').convert(backup.toJson());\n  }\n}\n"
  },
  {
    "path": "lib/features/per_app_proxy/overview/per_app_proxy_page.dart",
    "content": "import 'package:dartx/dartx.dart';\nimport 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/region.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/router/bottom_sheets/bottom_sheets_notifier.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/per_app_proxy/model/app_package_info.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_mode.dart';\nimport 'package:hiddify/features/per_app_proxy/model/pkg_flag.dart';\nimport 'package:hiddify/features/per_app_proxy/overview/per_app_proxy_loading_notifier.dart';\nimport 'package:hiddify/features/per_app_proxy/overview/per_app_proxy_notifier.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:installed_apps/index.dart';\n\nclass PerAppProxyPage extends HookConsumerWidget with PresLogger {\n  const PerAppProxyPage({super.key});\n\n  int _getPriority(AppPackageInfo app, Map<String, int> selected) {\n    final flag = selected[app.packageName];\n    if (flag == null) return 4;\n    if (PkgFlag.userSelection.check(flag)) {\n      return 1;\n    } else if (PkgFlag.autoSelection.check(flag) && !PkgFlag.forceDeselection.check(flag)) {\n      return 2;\n    } else {\n      return 3;\n    }\n  }\n\n  Future<Set<AppPackageInfo>> getApps(bool hideSystem) async {\n    if (!PlatformUtils.isAndroid) return {};\n    return (await InstalledApps.getInstalledApps(\n      hideSystem,\n      true,\n    )).map((e) => AppPackageInfo(packageName: e.packageName, name: e.name, icon: e.icon)).toSet();\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final theme = Theme.of(context);\n    final t = ref.watch(translationsProvider).requireValue;\n    final localizations = MaterialLocalizations.of(context);\n\n    final mode = ref.watch(Preferences.perAppProxyMode).toAppProxy();\n    final selectedApps = ref.watch(PerAppProxyProvider(mode));\n\n    final hideSystemApps = useState(false);\n    final isSearching = useState(false);\n    final searchQuery = useState(\"\");\n    final sortListener = useState(false);\n\n    final asyncApps = useFuture(useMemoized(() => getApps(false)));\n    final asyncAppsHideSys = useFuture(useMemoized(() => getApps(true)));\n\n    final asyncFilteredApps = hideSystemApps.value ? asyncAppsHideSys : asyncApps;\n\n    final displayedApps = useMemoized<AsyncValue<List<AppPackageInfo>>>(\n      () {\n        if (!(selectedApps.hasValue &&\n            selectedApps is AsyncData &&\n            asyncFilteredApps.hasData &&\n            asyncFilteredApps.connectionState == ConnectionState.done))\n          return const AsyncValue.loading();\n        final appsList = asyncFilteredApps.requireData.toList();\n        if (searchQuery.value.isBlank) {\n          appsList.sort((a, b) {\n            final priorityA = _getPriority(a, selectedApps.requireValue);\n            final priorityB = _getPriority(b, selectedApps.requireValue);\n            return priorityA.compareTo(priorityB);\n          });\n          return AsyncValue.data(appsList);\n        }\n        final filteredAppsList = appsList\n            .filter((e) => e.name.toLowerCase().contains(searchQuery.value.toLowerCase()))\n            .toList();\n        return AsyncValue.data(filteredAppsList);\n      },\n      [\n        asyncFilteredApps.connectionState == ConnectionState.done,\n        hideSystemApps.value,\n        selectedApps.hasValue,\n        searchQuery.value,\n        sortListener.value,\n      ],\n    );\n\n    if (mode != null) {\n      ref.listen(PerAppProxyProvider(mode), (previous, next) {\n        if (previous != null) {\n          if ((previous, next) case (AsyncData(value: final prevData), AsyncData(value: final nextData))) {\n            if (nextData.isNotEmpty) {\n              if ((nextData.length - prevData.length).abs() > 1) sortListener.value = !sortListener.value;\n            }\n          }\n        }\n      });\n    }\n\n    final scrollController = useScrollController();\n    const double scrollThreshold = 300.0;\n    final showScrollToTop = useState<bool>(false);\n    useEffect(() {\n      void listener() {\n        showScrollToTop.value = scrollController.offset > scrollThreshold;\n      }\n\n      scrollController.addListener(listener);\n      return () => scrollController.removeListener(listener);\n    }, []);\n    useEffect(() {\n      showScrollToTop.value = false;\n      return null;\n    }, [displayedApps]);\n\n    return Scaffold(\n      appBar: isSearching.value\n          ? AppBar(\n              title: TextFormField(\n                onChanged: (value) => searchQuery.value = value,\n                autofocus: true,\n                decoration: InputDecoration(\n                  hintText: \"${localizations.searchFieldLabel}...\",\n                  isDense: true,\n                  filled: false,\n                  border: InputBorder.none,\n                  focusedBorder: InputBorder.none,\n                  enabledBorder: InputBorder.none,\n                  errorBorder: InputBorder.none,\n                  focusedErrorBorder: InputBorder.none,\n                  disabledBorder: InputBorder.none,\n                ),\n              ),\n              leading: IconButton(\n                onPressed: () {\n                  searchQuery.value = \"\";\n                  isSearching.value = false;\n                },\n                icon: const Icon(Icons.close),\n                tooltip: localizations.cancelButtonLabel,\n              ),\n            )\n          : AppBar(\n              title: Text(t.pages.settings.routing.perAppProxy.title),\n              actions: [\n                IconButton(\n                  icon: const Icon(FluentIcons.search_24_regular),\n                  onPressed: () => isSearching.value = true,\n                  tooltip: localizations.searchFieldLabel,\n                ),\n                MenuAnchor(\n                  menuChildren: <Widget>[\n                    SubmenuButton(\n                      menuChildren: <Widget>[\n                        MenuItemButton(\n                          child: Text(t.pages.settings.routing.perAppProxy.options.import.clipboard),\n                          onPressed: () async => await ref\n                              .read(dialogNotifierProvider.notifier)\n                              .showConfirmation(\n                                title: t.common.msg.import.confirm,\n                                message: t.dialogs.confirmation.perAppProxy.import.msg,\n                              )\n                              .then((shouldImport) async {\n                                if (shouldImport) await ref.read(PerAppProxyProvider(mode).notifier).importClipboard();\n                              }),\n                        ),\n                        MenuItemButton(\n                          child: Text(t.pages.settings.routing.perAppProxy.options.import.file),\n                          onPressed: () async => await ref\n                              .read(dialogNotifierProvider.notifier)\n                              .showConfirmation(\n                                title: t.pages.settings.routing.perAppProxy.options.import.file,\n                                message: t.pages.settings.routing.perAppProxy.options.import.msg,\n                              )\n                              .then((shouldImport) async {\n                                if (shouldImport) await ref.read(PerAppProxyProvider(mode).notifier).importFile();\n                              }),\n                        ),\n                      ],\n                      child: Text(t.common.import),\n                    ),\n                    SubmenuButton(\n                      menuChildren: <Widget>[\n                        MenuItemButton(\n                          child: Text(t.pages.settings.routing.perAppProxy.options.export.clipboard),\n                          onPressed: () async => await ref.read(PerAppProxyProvider(mode).notifier).exportClipboard(),\n                        ),\n                        MenuItemButton(\n                          child: Text(t.pages.settings.routing.perAppProxy.options.export.file),\n                          onPressed: () async => await ref.read(PerAppProxyProvider(mode).notifier).exportFile(),\n                        ),\n                      ],\n                      child: Text(t.common.export),\n                    ),\n                    if (ref.watch(ConfigOptions.region) != Region.other)\n                      MenuItemButton(\n                        child: Text(t.pages.settings.routing.perAppProxy.options.shareToAll),\n                        onPressed: () async => await ref\n                            .read(appProxyLoadingProvider.notifier)\n                            .doAsync(ref.read(PerAppProxyProvider(mode).notifier).shareOnGithub),\n                      ),\n                    const PopupMenuDivider(),\n                    MenuItemButton(\n                      child: Text(t.pages.settings.routing.perAppProxy.options.clearAllSelections),\n                      onPressed: () => ref.read(PerAppProxyProvider(mode).notifier).clearAll(),\n                    ),\n                  ],\n                  builder: (context, controller, child) => AnimatedSwitcher(\n                    duration: const Duration(milliseconds: 300),\n                    child: ref.watch(appProxyLoadingProvider)\n                        ? const Padding(\n                            padding: EdgeInsets.all(8),\n                            child: SizedBox(width: 32, height: 32, child: CircularProgressIndicator()),\n                          )\n                        : IconButton(\n                            onPressed: () {\n                              if (controller.isOpen) {\n                                controller.close();\n                              } else {\n                                controller.open();\n                              }\n                            },\n                            icon: const Icon(Icons.more_vert_rounded),\n                          ),\n                  ),\n                ),\n              ],\n              bottom: PreferredSize(\n                preferredSize: const Size.fromHeight(48),\n                child: Expanded(\n                  child: ListView(\n                    scrollDirection: Axis.horizontal,\n                    padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),\n                    children: [\n                      PopupMenuButton(\n                        borderRadius: BorderRadius.circular(8),\n                        position: PopupMenuPosition.under,\n                        tooltip: (mode?.toPerAppProxy() ?? PerAppProxyMode.off).present(t).message,\n                        initialValue: mode?.toPerAppProxy() ?? PerAppProxyMode.off,\n                        onSelected: (e) async {\n                          if (ref.read(Preferences.autoAppsSelectionRegion) != null)\n                            await ref.read(PerAppProxyProvider(mode).notifier).clearAutoSelected();\n                          if (e == PerAppProxyMode.off && context.mounted) context.pop();\n                          await ref.read(Preferences.perAppProxyMode.notifier).update(e);\n                        },\n                        itemBuilder: (context) => PerAppProxyMode.values\n                            .map((e) => PopupMenuItem(value: e, child: Text(e.present(t).message)))\n                            .toList(),\n                        child: Container(\n                          decoration: BoxDecoration(\n                            borderRadius: BorderRadius.circular(8),\n                            color: theme.colorScheme.surface,\n                            border: Border.all(color: theme.colorScheme.outlineVariant),\n                          ),\n                          child: Row(\n                            children: [\n                              const Gap(16),\n                              Text(mode?.present(t).title ?? ''),\n                              const Gap(4),\n                              Icon(Icons.arrow_drop_down_rounded, color: theme.colorScheme.onSurfaceVariant),\n                              const Gap(8),\n                            ],\n                          ),\n                        ),\n                      ),\n                      const Gap(8),\n                      ChoiceChip(\n                        label: Text(t.pages.settings.routing.perAppProxy.hideSysApps),\n                        selected: hideSystemApps.value,\n                        onSelected: (value) => hideSystemApps.value = value,\n                      ),\n                    ],\n                  ),\n                ),\n              ),\n            ),\n      floatingActionButton: showScrollToTop.value\n          ? FloatingActionButton(\n              onPressed: () =>\n                  scrollController.animateTo(0.0, duration: const Duration(milliseconds: 500), curve: Curves.easeOut),\n              child: const Icon(Icons.keyboard_arrow_up_rounded),\n            )\n          : (ref.watch(ConfigOptions.region) != Region.other)\n          ? FloatingActionButton.extended(\n              onPressed: () async =>\n                  await ref.read(bottomSheetsNotifierProvider.notifier).showAutoAppsSelection(mode: mode!),\n              label: Text(t.pages.settings.routing.perAppProxy.autoSelection.title),\n              icon: Icon(\n                ref.watch(Preferences.autoAppsSelectionRegion) == null\n                    ? Icons.toggle_off_outlined\n                    : Icons.toggle_on_rounded,\n              ),\n            )\n          : null,\n      body: displayedApps.when(\n        data: (packages) => ListView.builder(\n          padding: const EdgeInsets.only(bottom: 88),\n          controller: scrollController,\n          itemBuilder: (context, index) {\n            final package = packages[index];\n            final flag = selectedApps.requireValue[package.packageName];\n            return CheckboxListTile.adaptive(\n              title: Row(\n                children: [\n                  Flexible(child: Text(package.name, maxLines: 1, overflow: TextOverflow.ellipsis)),\n                  if (flag != null && PkgFlag.forceDeselection.check(flag)) ...[\n                    const Gap(6),\n                    Container(\n                      width: 6,\n                      height: 6,\n                      decoration: BoxDecoration(color: theme.colorScheme.error, shape: BoxShape.circle),\n                    ),\n                  ],\n                ],\n              ),\n              subtitle: Text(\n                package.packageName,\n                style: Theme.of(context).textTheme.bodySmall,\n                maxLines: 1,\n                overflow: TextOverflow.ellipsis,\n              ),\n              value: flag == null ? false : PkgFlag.checkboxValue(flag),\n              tristate: true,\n              onChanged: (_) => ref.read(PerAppProxyProvider(mode).notifier).updatePkg(package.packageName),\n              secondary: package.icon == null\n                  ? null\n                  : Image.memory(package.icon!, width: 48, height: 48, cacheWidth: 48, cacheHeight: 48),\n            );\n          },\n          itemCount: packages.length,\n        ),\n        error: (error, _) => SliverErrorBodyPlaceholder(error.toString()),\n        loading: () => const Center(child: CircularProgressIndicator()),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/per_app_proxy/overview/per_app_proxy_service_notifier.dart",
    "content": "import 'dart:async';\n\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/features/per_app_proxy/data/selected_data_provider.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_mode.dart';\nimport 'package:hiddify/features/per_app_proxy/overview/per_app_proxy_notifier.dart';\nimport 'package:installed_apps/index.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'per_app_proxy_service_notifier.g.dart';\n\n@riverpod\nclass PerAppProxyService extends _$PerAppProxyService {\n  StreamSubscription? _includeSubscription;\n  StreamSubscription? _excludeSubscription;\n  Timer? _timer;\n  @override\n  Future<void> build() async {\n    final phonePkgs = (await InstalledApps.getInstalledApps(false)).map((e) => e.packageName).toSet();\n    _includeSubscription = ref\n        .read(appProxyDataSourceProvider)\n        .watchActivePackages(phonePkgs: phonePkgs, mode: AppProxyMode.include)\n        .listen((pkgs) => ref.read(Preferences.includeApps.notifier).update(pkgs));\n    _excludeSubscription = ref\n        .read(appProxyDataSourceProvider)\n        .watchActivePackages(phonePkgs: phonePkgs, mode: AppProxyMode.exclude)\n        .listen((pkgs) => ref.read(Preferences.excludeApps.notifier).update(pkgs));\n\n    _timer = Timer.periodic(const Duration(days: 1), (_) async => await _autoSelectionUpdate());\n    ref.onDispose(() {\n      _includeSubscription?.cancel();\n      _excludeSubscription?.cancel();\n      _timer?.cancel();\n    });\n    await _autoSelectionUpdate();\n  }\n\n  Future<void> _autoSelectionUpdate() async {\n    final autoRegion = ref.read(Preferences.autoAppsSelectionRegion);\n    if (autoRegion == null) return;\n    final mode = ref.read(Preferences.perAppProxyMode).toAppProxy();\n    final lastUpdate = ref.read(Preferences.autoAppsSelectionLastUpdate);\n    final days = ref.read(Preferences.autoAppsSelectionUpdateInterval).round();\n    final interval = Duration(days: days);\n    if (mode != null && (lastUpdate == null || DateTime.now().difference(lastUpdate) > interval)) {\n      final rs = await ref.read(PerAppProxyProvider(mode).notifier).applyAutoSelection();\n      if (rs) {\n        final t = ref.read(translationsProvider).requireValue;\n        ref\n            .read(inAppNotificationControllerProvider)\n            .showSuccessToast(t.pages.settings.routing.perAppProxy.autoSelection.toast.success);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "lib/features/platform_specific/android_quick_settings_tile.dart",
    "content": "// void setTileLable(Tile tile, WidgetRef ref) {\n//   final t = ref.watch(translationsProvider).requireValue;\n//   final connectionStatus = ref.watch(connectionNotifierProvider);\n//   final activeProfile = ref.watch(activeProfileProvider).valueOrNull;\n//   tile.label = activeProfile?.name ?? t.general.appTitle;\n\n//   final activeProxy = ref.watch(activeProxyNotifierProvider);\n//   final delay = activeProxy.valueOrNull?.urlTestDelay ?? 0;\n\n//   tile.subtitle = switch (connectionStatus) {\n//     AsyncData(value: Connected()) when delay <= 0 || delay >= 65000 => t.connection.connecting,\n//     AsyncData(value: Connected()) => \"{delay}ms\",\n//     _ => \"\",\n//   };\n// }\n\n// // QuickSettings setup\n// void setupQuickSettings(WidgetRef ref) {\n//   final connectionStatus = ref.read(connectionNotifierProvider.notifier);\n//   @pragma(\"vm:entry-point\")\n//   Tile onTileClicked(Tile tile) {\n//     final t = ref.read(translationsProvider).requireValue;\n\n//     final oldStatus = tile.tileStatus;\n//     connectionStatus.toggleConnection();\n//     if (oldStatus == TileStatus.active) {\n//       tile.tileStatus = TileStatus.inactive;\n//       tile.subtitle = t.connection.disconnecting;\n//     } else {\n//       tile.tileStatus = TileStatus.active;\n//       tile.subtitle = t.connection.connecting;\n//     }\n//     return tile;\n//   }\n\n//   @pragma(\"vm:entry-point\")\n//   Tile onTileAdded(Tile tile) {\n//     setTileLable(tile, ref);\n//     return tile;\n//   }\n\n//   @pragma(\"vm:entry-point\")\n//   void onTileRemoved() {\n//     print(\"Tile removed\");\n//   }\n\n//   QuickSettings.setup(\n//     onTileClicked: onTileClicked,\n//     onTileAdded: onTileAdded,\n//     onTileRemoved: onTileRemoved,\n//   );\n\n//   final t = ref.read(translationsProvider).requireValue;\n\n//   QuickSettings.addTileToQuickSettings(label: t.general.appTitle, drawableName: \"ic_launcher\");\n// }\n"
  },
  {
    "path": "lib/features/profile/add/add_profile_modal.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/features/profile/add/widgets/free_btns.dart';\nimport 'package:hiddify/features/profile/add/widgets/widgets.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/features/profile/notifier/profile_notifier.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass AddProfileModal extends HookConsumerWidget {\n  const AddProfileModal({super.key, this.url});\n  // static const warpConsentGiven = \"warp_consent_given\";\n  final String? url;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final isLoading = ref.watch(addProfileNotifierProvider).isLoading;\n    final currentWidget = ref.watch(addProfilePageNotifierProvider);\n    ref.listen(freeSwitchNotifierProvider, (_, _) {});\n    ref.listen(addProfileNotifierProvider, (previous, next) {\n      if (next case AsyncData(value: final _?)) {\n        WidgetsBinding.instance.addPostFrameCallback((_) {\n          if (context.mounted && context.canPop()) context.pop();\n        });\n      }\n    });\n\n    useMemoized(() async {\n      await Future.delayed(const Duration(milliseconds: 200));\n      if (url != null && context.mounted) {\n        if (isLoading) return;\n        ref.read(addProfileNotifierProvider.notifier).addClipboard(url!);\n      }\n    });\n    return SafeArea(\n      child: isLoading\n          ? const ProfileLoading()\n          : switch (currentWidget) {\n              AddProfilePages.options => const AddProfileOptions(),\n              AddProfilePages.manual => const AddProfileManual(),\n            },\n    );\n  }\n}\n\nclass AddProfileOptions extends HookConsumerWidget {\n  const AddProfileOptions({super.key});\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    // final isLoadingProfile = ref.watch(addProfileNotifierProvider).isLoading;\n    final freeSwitch = ref.watch(freeSwitchNotifierProvider);\n    final isDesktop = PlatformUtils.isDesktop;\n    return LayoutBuilder(\n      builder: (context, constraints) {\n        final fixBtnsHeight =\n            (constraints.maxWidth - AddProfileModalConst.fixBtnsGap * AddProfileModalConst.fixBtnsGapCount) /\n            AddProfileModalConst.fixBtnsItemCount;\n        final fullHeight = fixBtnsHeight + AddProfileModalConst.navBarHeight + 32;\n        final initial = !freeSwitch ? fullHeight : fullHeight + 180;\n        var min = !freeSwitch ? fullHeight : fullHeight + 100;\n        var max = !freeSwitch ? fullHeight / constraints.maxHeight : 0.85;\n        if (isDesktop) {\n          min = initial;\n          max = initial / constraints.maxHeight;\n        }\n        return DraggableScrollableSheet(\n          initialChildSize: initial / constraints.maxHeight,\n          minChildSize: min / constraints.maxHeight,\n          maxChildSize: max,\n          expand: false,\n          builder: (context, scrollController) => Column(\n            children: [\n              const Gap(AddProfileModalConst.fixBtnsGap),\n              FixBtns(height: fixBtnsHeight),\n              if (freeSwitch) Expanded(child: FreeBtns(scrollController: scrollController)) else const Spacer(),\n              const NavBar(),\n            ],\n          ),\n        );\n      },\n    );\n  }\n}\n\nclass AddProfileManual extends HookConsumerWidget {\n  const AddProfileManual({super.key});\n\n  String _genSliderText(Translations t, int sliderValue) {\n    if (sliderValue == 0) {\n      return t.common.auto;\n    } else if (sliderValue < 24) {\n      return t.common.interval.hour(n: sliderValue);\n    }\n    final day = t.common.interval.day(n: sliderValue ~/ 24);\n    final hour = t.common.interval.hour(n: sliderValue % 24);\n    return '$day $hour';\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final theme = Theme.of(context);\n    final t = ref.watch(translationsProvider).requireValue;\n    final formKey = useMemoized(() => GlobalKey<FormState>());\n    final nameTextController = useTextEditingController();\n    final urlTextController = useTextEditingController();\n    final isAutoUpdateDisable = useState<bool>(false);\n    final updateInterval = useState(.0);\n    final sliderFocusNode = useFocusNode(\n      onKeyEvent: (node, event) {\n        if (KeyboardConst.verticalArrows.contains(event.logicalKey) && event is KeyDownEvent) {\n          if (event.logicalKey == LogicalKeyboardKey.arrowUp) {\n            node.previousFocus();\n          } else {\n            node.nextFocus();\n          }\n          return KeyEventResult.handled;\n        }\n        return KeyEventResult.ignored;\n      },\n    );\n    return Form(\n      key: formKey,\n      child: Column(\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          Padding(\n            padding: const EdgeInsetsDirectional.fromSTEB(16, 8, 8, 12),\n            child: Row(\n              children: [\n                Expanded(child: Text(t.common.manually, style: theme.textTheme.headlineMedium)),\n                IconButton(\n                  icon: const Icon(Icons.close),\n                  onPressed: () => ref.read(addProfilePageNotifierProvider.notifier).goOptions(),\n                ),\n              ],\n            ),\n          ),\n          Padding(\n            padding: const EdgeInsets.symmetric(horizontal: 16),\n            child: CustomTextFormField(\n              maxLines: 1,\n              controller: nameTextController,\n              validator: (value) => (value?.isEmpty ?? true) ? t.pages.profileDetails.form.emptyName : null,\n              label: t.common.name,\n              hint: t.pages.profileDetails.form.nameHint,\n            ),\n          ),\n          const Gap(16),\n          Padding(\n            padding: const EdgeInsets.symmetric(horizontal: 16),\n            child: CustomTextFormField(\n              maxLines: 1,\n              controller: urlTextController,\n              validator: (value) => (value != null && !isUrl(value)) ? t.pages.profileDetails.form.invalidUrl : null,\n              label: t.common.url,\n              hint: t.pages.profileDetails.form.urlHint,\n            ),\n          ),\n          const Gap(12),\n          SwitchListTile.adaptive(\n            title: Text(\n              t.pages.profileDetails.form.disableAutoUpdate,\n              style: theme.textTheme.titleSmall!.copyWith(color: theme.colorScheme.onSurface),\n            ),\n            value: isAutoUpdateDisable.value,\n            onChanged: (value) => isAutoUpdateDisable.value = value,\n          ),\n          AnimatedSize(\n            alignment: Alignment.topCenter,\n            duration: const Duration(milliseconds: 300),\n            curve: Curves.easeInOut,\n            child: !isAutoUpdateDisable.value\n                ? Column(\n                    children: [\n                      const Divider(indent: 16, endIndent: 16),\n                      const Gap(12),\n                      Padding(\n                        padding: const EdgeInsets.symmetric(horizontal: 16),\n                        child: Row(\n                          children: [\n                            Expanded(\n                              child: Text(\n                                t.pages.profileDetails.form.autoUpdateInterval,\n                                style: theme.textTheme.titleSmall!.copyWith(color: theme.colorScheme.onSurface),\n                              ),\n                            ),\n                            Text(\n                              _genSliderText(t, updateInterval.value.round()),\n                              style: theme.textTheme.labelSmall!.copyWith(color: theme.colorScheme.onSurfaceVariant),\n                            ),\n                          ],\n                        ),\n                      ),\n                      const Gap(4),\n                      Padding(\n                        padding: const EdgeInsets.symmetric(horizontal: 10),\n                        child: Slider(\n                          focusNode: sliderFocusNode,\n                          value: updateInterval.value,\n                          max: 96,\n                          divisions: 96,\n                          label: updateInterval.value.round().toString(),\n                          onChanged: (double value) => updateInterval.value = value,\n                        ),\n                      ),\n                    ],\n                  )\n                : const SizedBox.shrink(),\n          ),\n\n          Padding(\n            padding: const EdgeInsets.symmetric(horizontal: 16).copyWith(bottom: 8),\n            child: Row(\n              children: [\n                Expanded(\n                  child: FilledButton(\n                    child: Text(t.common.add),\n                    onPressed: () async {\n                      if (formKey.currentState!.validate()) {\n                        final i = updateInterval.value.toInt();\n                        final interval = i > 0 ? i : null;\n                        await ref\n                            .read(addProfileNotifierProvider.notifier)\n                            .addManual(\n                              url: urlTextController.text.trim(),\n                              userOverride: UserOverride(\n                                name: nameTextController.text.trim(),\n                                isAutoUpdateDisable: isAutoUpdateDisable.value,\n                                updateInterval: interval,\n                              ),\n                            );\n                      }\n                    },\n                  ),\n                ),\n              ],\n            ),\n          ),\n          // const Gap(16),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/add/model/free_profiles_model.dart",
    "content": "// This file is \"main.dart\"\r\nimport 'package:flutter/foundation.dart';\r\nimport 'package:freezed_annotation/freezed_annotation.dart';\r\n\r\npart 'free_profiles_model.freezed.dart';\r\npart 'free_profiles_model.g.dart';\r\n\r\n@freezed\r\nclass FreeProfilesModel with _$FreeProfilesModel {\r\n  const factory FreeProfilesModel({required List<FreeProfile> profiles}) = _FreeProfilesModel;\r\n\r\n  factory FreeProfilesModel.fromJson(Map<String, Object?> json) => _$FreeProfilesModelFromJson(json);\r\n}\r\n\r\n@freezed\r\nclass FreeProfile with _$FreeProfile {\r\n  const factory FreeProfile({\r\n    required List<String> region,\r\n    required StringByLocale title,\r\n    required String sublink,\r\n    required ListOfStringByLocale tags,\r\n    required StringByLocale consent,\r\n    @JsonKey(name: 'needed_features') List<String>? neededFeatures,\r\n  }) = _FreeProfile;\r\n\r\n  factory FreeProfile.fromJson(Map<String, Object?> json) => _$FreeProfileFromJson(json);\r\n}\r\n\r\n@freezed\r\nclass StringByLocale with _$StringByLocale {\r\n  const factory StringByLocale({required String en, required String fa}) = _StringByLocale;\r\n\r\n  factory StringByLocale.fromJson(Map<String, Object?> json) => _$StringByLocaleFromJson(json);\r\n}\r\n\r\n@freezed\r\nclass ListOfStringByLocale with _$ListOfStringByLocale {\r\n  const factory ListOfStringByLocale({required List<String> en, required List<String> fa}) = _ListOfStringByLocale;\r\n\r\n  factory ListOfStringByLocale.fromJson(Map<String, Object?> json) => _$ListOfStringByLocaleFromJson(json);\r\n}\r\n"
  },
  {
    "path": "lib/features/profile/add/widgets/fix_btn.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hiddify/core/router/go_router/helper/active_breakpoint_notifier.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass FixBtn extends ConsumerWidget {\r\n  const FixBtn({super.key, required this.height, required this.title, required this.icon, required this.onTap});\r\n\r\n  final double height;\r\n  final String title;\r\n  final IconData icon;\r\n  final GestureTapCallback onTap;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final theme = Theme.of(context);\r\n    final isMobile = Breakpoint(context).isMobile();\r\n    final color = theme.colorScheme.primary;\r\n    final borderRadius = BorderRadius.circular(18);\r\n\r\n    return Expanded(\r\n      child: InkWell(\r\n        onTap: onTap,\r\n        borderRadius: borderRadius,\r\n        child: Container(\r\n          alignment: Alignment.center,\r\n          height: height,\r\n          padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),\r\n          decoration: BoxDecoration(\r\n            borderRadius: borderRadius,\r\n            border: Border.all(color: theme.colorScheme.outlineVariant),\r\n          ),\r\n          child: Column(\r\n            mainAxisSize: MainAxisSize.min,\r\n            children: [\r\n              Icon(icon, size: isMobile ? 32 : 40, color: color),\r\n              Gap(isMobile ? 4 : 8),\r\n              Text(\r\n                title,\r\n                style: isMobile\r\n                    ? theme.textTheme.titleSmall!.copyWith(color: color)\r\n                    : theme.textTheme.titleMedium!.copyWith(color: color),\r\n                overflow: TextOverflow.ellipsis,\r\n                maxLines: 1,\r\n              ),\r\n            ],\r\n          ),\r\n        ),\r\n      ),\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/profile/add/widgets/fix_btns.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:flutter/services.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/core/model/constants.dart';\r\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\r\nimport 'package:hiddify/features/profile/add/widgets/widgets.dart';\r\nimport 'package:hiddify/features/profile/notifier/profile_notifier.dart';\r\nimport 'package:hiddify/utils/utils.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass FixBtns extends ConsumerWidget {\r\n  const FixBtns({super.key, required this.height});\r\n  final double height;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n\r\n    final isDesktop = PlatformUtils.isDesktop;\r\n    return Row(\r\n      children: [\r\n        if (!isDesktop) ...[\r\n          const Gap(AddProfileModalConst.fixBtnsGap),\r\n          FixBtn(\r\n            key: const ValueKey('add_by_qr_code_button'),\r\n            height: height,\r\n            title: t.common.scanQr,\r\n            icon: Icons.qr_code_scanner,\r\n            onTap: () async {\r\n              final cr = await ref.read(dialogNotifierProvider.notifier).showQrScanner();\r\n              if (cr == null) return;\r\n              ref.read(addProfileNotifierProvider.notifier).addClipboard(cr);\r\n            },\r\n          ),\r\n        ],\r\n        const Gap(AddProfileModalConst.fixBtnsGap),\r\n        FixBtn(\r\n          key: const ValueKey('add_from_clipboard_button'),\r\n          height: height,\r\n          title: t.common.clipboard,\r\n          icon: Icons.content_paste,\r\n          onTap: () async {\r\n            final cr = await Clipboard.getData(Clipboard.kTextPlain).then((value) => value?.text ?? '');\r\n            ref.read(addProfileNotifierProvider.notifier).addClipboard(cr);\r\n          },\r\n        ),\r\n        const Gap(AddProfileModalConst.fixBtnsGap),\r\n        FixBtn(\r\n          key: const ValueKey('add_manually_button'),\r\n          height: height,\r\n          title: t.common.manually,\r\n          icon: Icons.add,\r\n          onTap: () {\r\n            ref.read(addProfilePageNotifierProvider.notifier).goManual();\r\n          },\r\n        ),\r\n        const Gap(AddProfileModalConst.fixBtnsGap),\r\n      ],\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/profile/add/widgets/free_btn.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hiddify/core/localization/locale_preferences.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/features/common/custom_text_scroll.dart';\r\nimport 'package:hiddify/features/profile/add/model/free_profiles_model.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass FreeBtn extends ConsumerWidget {\r\n  const FreeBtn({super.key, required this.freeProfile, required this.onTap});\r\n\r\n  final FreeProfile freeProfile;\r\n  final GestureTapCallback onTap;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    final locale = ref.watch(localePreferencesProvider);\r\n    final isFa = locale.name == AppLocale.fa.name;\r\n    final theme = Theme.of(context);\r\n    final borderRadius = BorderRadius.circular(18);\r\n\r\n    return Material(\r\n      borderRadius: borderRadius,\r\n      child: InkWell(\r\n        onTap: onTap,\r\n        borderRadius: borderRadius,\r\n        child: Container(\r\n          height: 72,\r\n          padding: const EdgeInsets.all(10),\r\n          decoration: BoxDecoration(\r\n            borderRadius: borderRadius,\r\n            border: Border.all(color: theme.colorScheme.outlineVariant),\r\n          ),\r\n          child: Column(\r\n            crossAxisAlignment: CrossAxisAlignment.end,\r\n            children: [\r\n              Expanded(\r\n                child: Row(\r\n                  crossAxisAlignment: CrossAxisAlignment.start,\r\n                  children: [\r\n                    Expanded(\r\n                      child: Text(\r\n                        isFa ? freeProfile.title.fa : freeProfile.title.en,\r\n                        maxLines: 1,\r\n                        overflow: TextOverflow.ellipsis,\r\n                        style: theme.textTheme.titleSmall!.copyWith(color: theme.colorScheme.onSurface),\r\n                      ),\r\n                    ),\r\n                    if (freeProfile.neededFeatures != null)\r\n                      Column(\r\n                        crossAxisAlignment: CrossAxisAlignment.start,\r\n                        children: [\r\n                          if (freeProfile.neededFeatures!.contains('warp_over_proxies'))\r\n                            Feature(title: t.common.warp, icon: Icons.add_moderator),\r\n                          if (freeProfile.neededFeatures!.contains('fragment'))\r\n                            Feature(title: t.common.fragment, icon: Icons.content_cut),\r\n                        ],\r\n                      ),\r\n                  ],\r\n                ),\r\n              ),\r\n              CustomTextScroll(\r\n                isFa ? freeProfile.tags.fa.join(' · ') : freeProfile.tags.en.join(' · '),\r\n                style: theme.textTheme.labelMedium!.copyWith(color: theme.colorScheme.onSurfaceVariant),\r\n              ),\r\n            ],\r\n          ),\r\n        ),\r\n      ),\r\n    );\r\n  }\r\n}\r\n\r\nclass Feature extends ConsumerWidget {\r\n  const Feature({super.key, required this.title, required this.icon});\r\n\r\n  final String title;\r\n  final IconData icon;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final theme = Theme.of(context);\r\n    final color = theme.colorScheme.primary;\r\n    return Row(\r\n      children: [\r\n        Icon(icon, size: 12, color: theme.colorScheme.primary),\r\n        const Gap(4),\r\n        Text(title, style: theme.textTheme.labelSmall!.copyWith(color: color)),\r\n      ],\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/profile/add/widgets/free_btns.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:hiddify/core/localization/locale_preferences.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/core/model/constants.dart';\r\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\r\nimport 'package:hiddify/features/profile/add/widgets/free_btn.dart';\r\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\r\nimport 'package:hiddify/features/profile/notifier/profile_notifier.dart';\r\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass FreeBtns extends ConsumerWidget {\r\n  const FreeBtns({super.key, required this.scrollController});\r\n\r\n  final ScrollController scrollController;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    final freeProfiles = ref.watch(freeProfilesNotifierProvider);\r\n    final freeProfilesFilteredByRegion = ref.watch(freeProfilesFilteredByRegionProvider);\r\n    final theme = Theme.of(context);\r\n    final locale = ref.watch(localePreferencesProvider);\r\n    final isFa = locale.name == AppLocale.fa.name;\r\n    return freeProfilesFilteredByRegion.when(\r\n      data: (data) => data.isNotEmpty\r\n          ? ScrollConfiguration(\r\n              behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),\r\n              child: GridView.builder(\r\n                controller: scrollController,\r\n                padding: const EdgeInsets.all(16).copyWith(bottom: 0),\r\n                itemCount: freeProfiles.value!.length,\r\n                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(\r\n                  crossAxisCount:\r\n                      MediaQuery.of(context).size.width <= BottomSheetConst.maxWidth || freeProfiles.value!.length < 2\r\n                      ? 1\r\n                      : 2,\r\n                  mainAxisSpacing: 8,\r\n                  crossAxisSpacing: 8,\r\n                  mainAxisExtent: 72,\r\n                ),\r\n                itemBuilder: (context, index) {\r\n                  final profile = freeProfiles.value![index];\r\n                  return FreeBtn(\r\n                    freeProfile: profile,\r\n                    onTap: () async {\r\n                      final title = isFa ? profile.title.fa : profile.title.en;\r\n                      final consent = isFa ? profile.consent.fa : profile.consent.en;\r\n                      final result = await ref\r\n                          .read(dialogNotifierProvider.notifier)\r\n                          .showFreeProfileConsent(title: title, consent: consent);\r\n                      if (result == true) {\r\n                        await ref\r\n                            .read(addProfileNotifierProvider.notifier)\r\n                            .addManual(\r\n                              url: profile.sublink,\r\n                              userOverride: UserOverride(\r\n                                name: title,\r\n                                updateInterval: 12,\r\n                                enableWarp: profile.neededFeatures?.contains('warp_over_proxies'),\r\n                                enableFragment: profile.neededFeatures?.contains('fragment'),\r\n                              ),\r\n                            );\r\n                      }\r\n                    },\r\n                  );\r\n                },\r\n              ),\r\n            )\r\n          : Center(\r\n              child: Text(\r\n                (freeProfiles.value?.isEmpty ?? true)\r\n                    ? t.pages.profiles.freeSubNotFound\r\n                    : t.pages.profiles.freeSubNotFoundForRegion(region: ref.watch(ConfigOptions.region).name),\r\n                style: theme.textTheme.bodySmall!.copyWith(color: theme.colorScheme.onSurface),\r\n              ),\r\n            ),\r\n      error: (error, stackTrace) => Center(\r\n        child: Text(\r\n          t.pages.profiles.failedToLoad,\r\n          style: theme.textTheme.bodyMedium!.copyWith(color: theme.colorScheme.onSurface),\r\n        ),\r\n      ),\r\n      loading: () => const Center(child: CircularProgressIndicator()),\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/profile/add/widgets/loading.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/features/profile/notifier/profile_notifier.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass ProfileLoading extends ConsumerWidget {\r\n  const ProfileLoading({super.key});\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    final theme = Theme.of(context);\r\n    return Padding(\r\n      padding: const EdgeInsets.symmetric(horizontal: 64, vertical: 64),\r\n      child: Column(\r\n        mainAxisSize: MainAxisSize.min,\r\n        children: [\r\n          Text(\r\n            t.pages.profileDetails.form.loading,\r\n            style: theme.textTheme.bodyMedium!.copyWith(color: theme.colorScheme.onSurface),\r\n          ),\r\n          const Gap(20),\r\n          const LinearProgressIndicator(backgroundColor: Colors.transparent),\r\n          const Gap(8),\r\n          TextButton(\r\n            onPressed: () {\r\n              ref.invalidate(addProfileNotifierProvider);\r\n            },\r\n            child: Text(MaterialLocalizations.of(context).cancelButtonLabel),\r\n          ),\r\n        ],\r\n      ),\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/profile/add/widgets/nav_bar.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/core/model/constants.dart';\r\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\r\nimport 'package:hiddify/features/profile/notifier/profile_notifier.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass NavBar extends ConsumerWidget {\r\n  const NavBar({super.key});\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final theme = Theme.of(context);\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    final freeSwitch = ref.watch(freeSwitchNotifierProvider);\r\n\r\n    final textColor = theme.colorScheme.onSurface;\r\n    return Padding(\r\n      padding: const EdgeInsets.all(\r\n        AddProfileModalConst.navBarGap,\r\n      ).copyWith(bottom: AddProfileModalConst.navBarBottomGap),\r\n      child: Row(\r\n        children: [\r\n          Row(\r\n            key: const ValueKey('free'),\r\n            children: [\r\n              Text(t.common.free, style: theme.textTheme.titleMedium!.copyWith(color: textColor)),\r\n              const Gap(8),\r\n              Switch(value: freeSwitch, onChanged: ref.read(freeSwitchNotifierProvider.notifier).onChange),\r\n            ],\r\n          ),\r\n          const Spacer(),\r\n          ActionChip(\r\n            key: const ValueKey(\"help\"),\r\n            label: Text(t.common.help, style: theme.textTheme.labelLarge!.copyWith(color: textColor)),\r\n            avatar: Icon(Icons.help_outline, color: theme.colorScheme.onSurfaceVariant),\r\n            onPressed: () async => await ref.read(dialogNotifierProvider.notifier).showNoActiveProfile(),\r\n          ),\r\n        ],\r\n      ),\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/profile/add/widgets/widgets.dart",
    "content": "export 'fix_btn.dart';\r\nexport 'fix_btns.dart';\r\nexport 'loading.dart';\r\nexport 'nav_bar.dart';\r\n"
  },
  {
    "path": "lib/features/profile/data/profile_data_mapper.dart",
    "content": "import 'dart:convert';\n\nimport 'package:drift/drift.dart';\nimport 'package:hiddify/core/db/db.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\n\nextension ProfileEntityMapper on ProfileEntity {\n  ProfileEntriesCompanion toInsertEntry() => map(\n    remote: (rp) => ProfileEntriesCompanion.insert(\n      id: rp.id,\n      type: ProfileType.remote,\n      active: rp.active,\n      name: rp.name,\n      url: Value(rp.url),\n      lastUpdate: rp.lastUpdate,\n      updateInterval: Value(rp.options?.updateInterval),\n      populatedHeaders: Value(jsonEncode(rp.populatedHeaders)),\n      profileOverride: Value(rp.profileOverride),\n      userOverride: Value(rp.userOverride?.toStr()),\n      upload: Value(rp.subInfo?.upload),\n      download: Value(rp.subInfo?.download),\n      total: Value(rp.subInfo?.total),\n      expire: Value(rp.subInfo?.expire),\n      webPageUrl: Value(rp.subInfo?.webPageUrl),\n      supportUrl: Value(rp.subInfo?.supportUrl),\n    ),\n    local: (lp) => ProfileEntriesCompanion.insert(\n      id: lp.id,\n      type: ProfileType.local,\n      active: lp.active,\n      name: lp.name,\n      lastUpdate: lp.lastUpdate,\n      populatedHeaders: Value(jsonEncode(lp.populatedHeaders)),\n      profileOverride: Value(lp.profileOverride),\n      userOverride: Value(lp.userOverride?.toStr()),\n    ),\n  );\n\n  ProfileEntriesCompanion toUpdateEntry() => map(\n    remote: (rp) => ProfileEntriesCompanion(\n      name: Value(rp.name),\n      lastUpdate: Value(rp.lastUpdate),\n      updateInterval: Value(rp.options?.updateInterval),\n      populatedHeaders: Value(jsonEncode(rp.populatedHeaders)),\n      profileOverride: Value(rp.profileOverride),\n      userOverride: Value(rp.userOverride?.toStr()),\n      upload: Value(rp.subInfo?.upload),\n      download: Value(rp.subInfo?.download),\n      total: Value(rp.subInfo?.total),\n      expire: Value(rp.subInfo?.expire),\n      webPageUrl: Value(rp.subInfo?.webPageUrl),\n      supportUrl: Value(rp.subInfo?.supportUrl),\n    ),\n    local: (lp) => ProfileEntriesCompanion(\n      name: Value(lp.name),\n      lastUpdate: Value(lp.lastUpdate),\n      populatedHeaders: Value(jsonEncode(lp.populatedHeaders)),\n      profileOverride: Value(lp.profileOverride),\n      userOverride: Value(lp.userOverride?.toStr()),\n    ),\n  );\n}\n\nextension ProfileEntryMapper on ProfileEntry {\n  ProfileEntity toEntity() {\n    ProfileOptions? options;\n    if (updateInterval != null) {\n      options = ProfileOptions(updateInterval: updateInterval!);\n    }\n\n    SubscriptionInfo? subInfo;\n    if (upload != null && download != null && total != null && expire != null) {\n      subInfo = SubscriptionInfo(\n        upload: upload!,\n        download: download!,\n        total: total!,\n        expire: expire!,\n        webPageUrl: webPageUrl,\n        supportUrl: supportUrl,\n      );\n    }\n    Map<String, dynamic>? mPopulatedHeaders;\n\n    if (populatedHeaders != null) {\n      final m = jsonDecode(populatedHeaders!) as Map;\n      mPopulatedHeaders = m.cast<String, dynamic>();\n    }\n\n    return switch (type) {\n      ProfileType.remote => RemoteProfileEntity(\n        id: id,\n        active: active,\n        name: name,\n        url: url!,\n        lastUpdate: lastUpdate,\n        options: options,\n        subInfo: subInfo,\n        populatedHeaders: mPopulatedHeaders,\n        profileOverride: profileOverride,\n        userOverride: UserOverride.fromStr(userOverride),\n      ),\n      ProfileType.local => LocalProfileEntity(\n        id: id,\n        active: active,\n        name: name,\n        lastUpdate: lastUpdate,\n        populatedHeaders: mPopulatedHeaders,\n        profileOverride: profileOverride,\n        userOverride: UserOverride.fromStr(userOverride),\n      ),\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/data/profile_data_providers.dart",
    "content": "import 'package:hiddify/core/db/provider/db_providers.dart';\nimport 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/core/http_client/http_client_provider.dart';\nimport 'package:hiddify/features/profile/data/profile_data_source.dart';\nimport 'package:hiddify/features/profile/data/profile_parser.dart';\nimport 'package:hiddify/features/profile/data/profile_path_resolver.dart';\nimport 'package:hiddify/features/profile/data/profile_repository.dart';\nimport 'package:hiddify/features/settings/data/config_option_data_providers.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service_provider.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'profile_data_providers.g.dart';\n\n@Riverpod(keepAlive: true)\nFuture<ProfileRepository> profileRepository(Ref ref) async {\n  final repo = ProfileRepositoryImpl(\n    profileDataSource: ref.watch(profileDataSourceProvider),\n    profilePathResolver: ref.watch(profilePathResolverProvider),\n    singbox: ref.watch(hiddifyCoreServiceProvider),\n    configOptionRepository: ref.watch(configOptionRepositoryProvider),\n    profileParser: ref.watch(profileParserProvider),\n  );\n  await repo.init().getOrElse((l) => throw l).run();\n  return repo;\n}\n\n@Riverpod(keepAlive: true)\nProfileDataSource profileDataSource(Ref ref) {\n  return ProfileDao(ref.watch(dbProvider));\n}\n\n@Riverpod(keepAlive: true)\nProfilePathResolver profilePathResolver(Ref ref) {\n  return ProfilePathResolver(ref.watch(appDirectoriesProvider).requireValue.workingDir);\n}\n\n@Riverpod(keepAlive: true)\nProfileParser profileParser(Ref ref) {\n  return ProfileParser(ref: ref, httpClient: ref.watch(httpClientProvider));\n}\n"
  },
  {
    "path": "lib/features/profile/data/profile_data_source.dart",
    "content": "import 'package:drift/drift.dart';\nimport 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/db/db.dart';\nimport 'package:hiddify/features/profile/model/profile_sort_enum.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:loggy/loggy.dart';\n\npart 'profile_data_source.g.dart';\n\nabstract interface class ProfileDataSource {\n  Future<ProfileEntry?> getById(String id);\n  Future<ProfileEntry?> getByUrl(String url);\n  Future<ProfileEntry?> getByName(String name);\n  Stream<ProfileEntry?> watchActiveProfile();\n  Stream<int> watchProfilesCount();\n  Stream<List<ProfileEntry>> watchAll({required ProfilesSort sort, required SortMode sortMode});\n  Future<void> insert(ProfileEntriesCompanion entry);\n  Future<void> edit(String id, ProfileEntriesCompanion entry);\n  Future<void> deleteById(String id, bool isActive);\n}\n\nMap<SortMode, OrderingMode> orderMap = {SortMode.ascending: OrderingMode.asc, SortMode.descending: OrderingMode.desc};\n\n@DriftAccessor(tables: [ProfileEntries])\nclass ProfileDao extends DatabaseAccessor<Db> with _$ProfileDaoMixin, InfraLogger implements ProfileDataSource {\n  ProfileDao(super.db);\n\n  @override\n  Future<ProfileEntry?> getById(String id) async {\n    return await (profileEntries.select()..where((tbl) => tbl.id.equals(id))).getSingleOrNull();\n  }\n\n  @override\n  Future<ProfileEntry?> getByUrl(String url) async {\n    return await (select(profileEntries)\n          ..where((tbl) => tbl.url.like('%$url%'))\n          ..limit(1))\n        .getSingleOrNull();\n  }\n\n  @override\n  Future<ProfileEntry?> getByName(String name) async {\n    return await (select(profileEntries)\n          ..where((tbl) => tbl.name.equals(name))\n          ..limit(1))\n        .getSingleOrNull();\n  }\n\n  @override\n  Stream<ProfileEntry?> watchActiveProfile() {\n    return (profileEntries.select()\n          ..where((tbl) => tbl.active.equals(true))\n          ..limit(1))\n        .watchSingleOrNull()\n        .distinct();\n  }\n\n  @override\n  Stream<int> watchProfilesCount() {\n    final count = profileEntries.id.count();\n    return (profileEntries.selectOnly()..addColumns([count])).map((exp) => exp.read(count)!).watchSingle().distinct();\n  }\n\n  @override\n  Stream<List<ProfileEntry>> watchAll({required ProfilesSort sort, required SortMode sortMode}) {\n    return (profileEntries.select()..orderBy([\n          (tbl) => OrderingTerm(expression: tbl.active, mode: OrderingMode.desc),\n          (tbl) {\n            final trafficRatio = (tbl.download + tbl.upload) / tbl.total;\n            final isExpired = tbl.expire.isSmallerOrEqualValue(DateTime.now());\n            return OrderingTerm(\n              expression:\n                  (trafficRatio.isNull() | trafficRatio.isSmallerThanValue(1)) &\n                  (isExpired.isNull() | isExpired.equals(false)),\n              mode: OrderingMode.desc,\n            );\n          },\n          switch (sort) {\n            ProfilesSort.name => (tbl) => OrderingTerm(expression: tbl.name, mode: orderMap[sortMode]!),\n            ProfilesSort.lastUpdate => (tbl) => OrderingTerm(expression: tbl.lastUpdate, mode: orderMap[sortMode]!),\n          },\n        ]))\n        .watch();\n  }\n\n  @override\n  Future<void> insert(ProfileEntriesCompanion entry) async {\n    await transaction(() async {\n      if (entry.active.present && entry.active.value) {\n        await update(profileEntries).write(const ProfileEntriesCompanion(active: Value(false)));\n      }\n      final name = StringBuffer(entry.name.value);\n      while (await getByName(name.toString()) != null) {\n        name.write('${randomInt(0, 9).run()}');\n      }\n      await into(profileEntries).insert(entry.copyWith(name: Value(name.toString())));\n    });\n  }\n\n  @override\n  Future<void> edit(String id, ProfileEntriesCompanion entry) async {\n    await transaction(() async {\n      final profile = await (profileEntries.select()..where((tbl) => tbl.id.equals(id))).getSingleOrNull();\n      if (profile == null) {\n        loggy.log(LogLevel.info, 'profile with id : [$id] deleted');\n        return;\n      }\n      if (entry.active.present && entry.active.value) {\n        await update(profileEntries).write(const ProfileEntriesCompanion(active: Value(false)));\n      }\n      await (update(profileEntries)..where((tbl) => tbl.id.equals(id))).write(entry);\n    });\n  }\n\n  @override\n  Future<void> deleteById(String id, bool isActive) async {\n    await transaction(() async {\n      await (delete(profileEntries)..where((tbl) => tbl.id.equals(id))).go();\n\n      if (isActive) {\n        final profiles = await (profileEntries.select()..where((tbl) => tbl.id.equals(id).not())).get();\n        if (profiles.isEmpty) return;\n        final prof = profiles.first;\n        await (update(\n          profileEntries,\n        )..where((tbl) => tbl.id.equals(prof.id))).write(const ProfileEntriesCompanion(active: Value(true)));\n      }\n    });\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/data/profile_parser.dart",
    "content": "import 'dart:convert';\nimport 'dart:io';\n\nimport 'package:dartx/dartx.dart';\nimport 'package:dio/dio.dart';\nimport 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/db/db.dart';\nimport 'package:hiddify/core/http_client/dio_http_client.dart';\nimport 'package:hiddify/features/profile/data/profile_data_mapper.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/features/profile/model/profile_failure.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/singbox/model/singbox_proxy_type.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:meta/meta.dart';\n\n/// parse profile subscription url and headers for data\n///\n/// ***name parser hierarchy:***\n/// - UserOverride.name\n/// - `profile-title` header\n/// - `content-disposition` header\n/// - url fragment (example: `https://example.com/config#user`) -> name=`user`\n/// - url filename extension (example: `https://example.com/config.json`) -> name=`config`\n/// - if none of these methods return a non-blank string, switch(profileType)\n/// - remote:  fallback to `Remote Profile`\n/// - local: fallback to protocol, extracted from content by protocol()\n\nclass ProfileParser {\n  static const infiniteTrafficThreshold = 920_233_720_368;\n  static const infiniteTimeThreshold = 92_233_720_368;\n  static const allowedOverrideConfigs = [\n    'connection-test-url',\n    'direct-dns-address',\n    'remote-dns-address',\n    'warp',\n    'warp2',\n    'tls-tricks',\n  ];\n  static const allowedProfileHeaders = [\n    'profile-title',\n    'content-disposition',\n    'subscription-userinfo',\n    'profile-update-interval',\n    'support-url',\n    'profile-web-page-url',\n    'enable-warp',\n    'enable-fragment',\n  ];\n\n  final Ref _ref;\n  final DioHttpClient _httpClient;\n\n  ProfileParser({required Ref ref, required DioHttpClient httpClient}) : _ref = ref, _httpClient = httpClient;\n  TaskEither<ProfileFailure, ProfileEntriesCompanion> addLocal({\n    required String id,\n    required String content,\n    required String tempFilePath,\n    required UserOverride? userOverride,\n  }) {\n    return TaskEither.tryCatch(() async {\n          await expandRemoteLinesInParallel(\n            tempFilePath: tempFilePath,\n            httpClient: _httpClient,\n            cancelToken: CancelToken(),\n            ref: _ref,\n          );\n        }, (_, __) => ProfileFailure.unexpected())\n        .flatMap((_) => TaskEither.fromEither(populateHeaders(content: content)))\n        .flatMap(\n          (populatedHeaders) => TaskEither.fromEither(\n            parse(\n              tempFilePath: tempFilePath,\n              profile: ProfileEntity.local(\n                id: id,\n                active: true,\n                name: '',\n                lastUpdate: DateTime.now(),\n                userOverride: userOverride,\n                populatedHeaders: populatedHeaders,\n              ),\n            ).flatMap((profEntity) => Either.tryCatch(() => profEntity.toInsertEntry(), ProfileFailure.unexpected)),\n          ),\n        );\n  }\n\n  TaskEither<ProfileFailure, ProfileEntriesCompanion> addRemote({\n    required String id,\n    required String url,\n    required String tempFilePath,\n    required UserOverride? userOverride,\n    CancelToken? cancelToken,\n  }) => _downloadProfile(url, tempFilePath, cancelToken).flatMap(\n    (remoteHeaders) =>\n        TaskEither.fromEither(\n          populateHeaders(content: File(tempFilePath).readAsStringSync(), remoteHeaders: remoteHeaders),\n        ).flatMap(\n          (populatedHeaders) => TaskEither.fromEither(\n            parse(\n              tempFilePath: tempFilePath,\n              profile: ProfileEntity.remote(\n                id: id,\n                active: true,\n                name: '',\n                url: url,\n                lastUpdate: DateTime.now(),\n                userOverride: userOverride,\n                populatedHeaders: populatedHeaders,\n              ),\n            ).flatMap((profEntity) => Either.tryCatch(() => profEntity.toInsertEntry(), ProfileFailure.unexpected)),\n          ),\n        ),\n  );\n\n  TaskEither<ProfileFailure, ProfileEntriesCompanion> updateRemote({\n    required RemoteProfileEntity rp,\n    required String tempFilePath,\n    CancelToken? cancelToken,\n  }) => _downloadProfile(rp.url, tempFilePath, cancelToken).flatMap(\n    (remoteHeaders) =>\n        TaskEither.fromEither(\n          populateHeaders(content: File(tempFilePath).readAsStringSync(), remoteHeaders: remoteHeaders),\n        ).flatMap(\n          (populatedHeaders) => TaskEither.fromEither(\n            parse(\n              tempFilePath: tempFilePath,\n              profile: rp.copyWith(populatedHeaders: populatedHeaders),\n            ).flatMap((profEntity) => Either.tryCatch(() => profEntity.toUpdateEntry(), ProfileFailure.unexpected)),\n          ),\n        ),\n  );\n\n  Either<ProfileFailure, ProfileEntriesCompanion> offlineUpdate({\n    required ProfileEntity profile,\n    required String tempFilePath,\n  }) => profile\n      .map(\n        remote: (rp) => parse(profile: rp, tempFilePath: tempFilePath),\n        local: (lp) => parse(tempFilePath: tempFilePath, profile: lp),\n      )\n      .flatMap((profEntity) => Either.tryCatch(() => profEntity.toUpdateEntry(), ProfileFailure.unexpected));\n\n  TaskEither<ProfileFailure, Map<String, dynamic>> _downloadProfile(\n    String url,\n    String tempFilePath,\n    CancelToken? cancelToken,\n  ) => TaskEither.tryCatch(() async {\n    // if (url.startsWith(\"http://\"))\n    //   throw const ProfileFailure.invalidUrl('HTTP is not supported. Please use HTTPS for secure connection.');\n\n    final rs = await _httpClient\n        .download(\n          url.trim(),\n          tempFilePath,\n          cancelToken: cancelToken,\n          userAgent: _ref.read(ConfigOptions.useXrayCoreWhenPossible)\n              ? _httpClient.userAgent.replaceAll(\"HiddifyNext\", \"HiddifyNextX\")\n              : null,\n        )\n        .catchError((err) {\n          if (CancelToken.isCancel(err as DioException)) {\n            throw const ProfileFailure.cancelByUser('HTTP request for getting profile content canceled by user.');\n          }\n          throw err;\n        });\n    await expandRemoteLinesInParallel(\n      tempFilePath: tempFilePath,\n      httpClient: _httpClient,\n      cancelToken: cancelToken ?? CancelToken(),\n      ref: _ref,\n    );\n    // fixing headers before return\n    return rs.headers.map.map((key, value) {\n      if (value.length == 1) return MapEntry(key, value.first);\n      return MapEntry(key, value);\n    });\n  }, (err, st) => err is ProfileFailure ? err : ProfileFailure.unexpected(err, st));\n  Future<void> expandRemoteLinesInParallel({\n    required String tempFilePath,\n    required DioHttpClient httpClient,\n    required CancelToken cancelToken,\n    required Ref ref,\n    int parallelism = 4,\n  }) async {\n    final content = await File(tempFilePath).readAsString();\n    final lines = content.split('\\n');\n\n    final results = List<String?>.filled(lines.length, null);\n\n    int index = 0;\n\n    Future<void> worker() async {\n      while (true) {\n        if (cancelToken.isCancelled) return;\n\n        final currentIndex = index++;\n        if (currentIndex >= lines.length) return;\n\n        final line = lines[currentIndex];\n\n        // Non-URL\n        if (!line.startsWith('http://') && !line.startsWith('https://')) {\n          results[currentIndex] = line.trim();\n          continue;\n        }\n\n        try {\n          final tmpPath = '$tempFilePath.$currentIndex';\n\n          await httpClient.download(\n            line,\n            tmpPath,\n            cancelToken: cancelToken,\n            userAgent: ref.read(ConfigOptions.useXrayCoreWhenPossible)\n                ? httpClient.userAgent.replaceAll('HiddifyNext', 'HiddifyNextX')\n                : null,\n          );\n\n          results[currentIndex] = (await File(tmpPath).readAsString()).trim();\n        } catch (err) {\n          if (err is DioException && CancelToken.isCancel(err)) {\n            return;\n          }\n          results[currentIndex] = '';\n        }\n      }\n    }\n\n    // Start workers\n    await Future.wait(List.generate(parallelism, (_) => worker()));\n\n    if (results.any((e) => e != null)) {\n      final newContent = results.join(\"\\n\");\n      await File(tempFilePath).writeAsString(newContent);\n    }\n  }\n\n  static Either<ProfileFailure, Map<String, dynamic>> populateHeaders({\n    required String content,\n    Map<String, dynamic>? remoteHeaders,\n  }) => Either.tryCatch(() {\n    final contentHeaders = _parseHeadersFromContent(content);\n    return _mergeAndValidateHeaders(contentHeaders, remoteHeaders ?? {});\n  }, ProfileFailure.unexpected);\n\n  static Map<String, dynamic> _mergeAndValidateHeaders(\n    Map<String, dynamic> contentHeaders,\n    Map<String, dynamic> remoteHeaders,\n  ) {\n    for (final entry in contentHeaders.entries) {\n      if (!remoteHeaders.keys.contains(entry.key)) {\n        remoteHeaders[entry.key] = entry.value;\n      }\n    }\n    final headers = <String, dynamic>{};\n    for (final entry in remoteHeaders.entries) {\n      if (allowedProfileHeaders.contains(entry.key) && entry.value != null && entry.value.toString().isNotEmpty) {\n        headers[entry.key] = entry.value;\n      }\n    }\n    return headers;\n  }\n\n  static Map<String, dynamic> _parseHeadersFromContent(String content) {\n    final headers = <String, dynamic>{};\n    final content_ = safeDecodeBase64(content);\n    final lines = content_.split(\"\\n\");\n    final linesToProcess = lines.length < 10 ? lines.length : 10;\n    for (int i = 0; i < linesToProcess; i++) {\n      final line = lines[i];\n      if (line.startsWith(\"#\") || line.startsWith(\"//\")) {\n        final index = line.indexOf(':');\n        if (index == -1) continue;\n        final key = line.substring(0, index).replaceFirst(RegExp(\"^#|//\"), \"\").trim().toLowerCase();\n        final value = line.substring(index + 1).trim();\n        headers[key] = value;\n      }\n    }\n    return headers;\n  }\n\n  static SubscriptionInfo? _parseSubscriptionInfo(String subInfoStr) {\n    final values = subInfoStr.split(';');\n    final map = {for (final v in values) v.split('=').first.trim(): num.tryParse(v.split('=').second.trim())?.toInt()};\n    if (map case {\"upload\": final upload?, \"download\": final download?, \"total\": final total, \"expire\": var expire}) {\n      final total1 = (total == null || total == 0) ? infiniteTrafficThreshold + 1 : total;\n      expire = (expire == null || expire == 0) ? infiniteTimeThreshold : expire;\n      return SubscriptionInfo(\n        upload: upload,\n        download: download,\n        total: total1,\n        expire: DateTime.fromMillisecondsSinceEpoch(expire * 1000),\n      );\n    }\n    return null;\n  }\n\n  @visibleForTesting\n  static Either<ProfileFailure, ProfileEntity> parse({required String tempFilePath, required ProfileEntity profile}) =>\n      Either.tryCatch(() {\n        final headers = Map<String, dynamic>.from(profile.populatedHeaders ?? {});\n        var name = '';\n        if (profile.userOverride?.name case final String oName when oName.isNotEmpty) {\n          name = oName;\n        }\n\n        if (headers['profile-title'] case final String titleHeader when name.isEmpty) {\n          if (titleHeader.startsWith(\"base64:\")) {\n            name = utf8.decode(base64.decode(titleHeader.replaceFirst(\"base64:\", \"\")));\n          } else {\n            name = titleHeader.trim();\n          }\n        }\n        if (headers['content-disposition'] case final String contentDispositionHeader when name.isEmpty) {\n          final regExp = RegExp('filename=\"([^\"]*)\"');\n          final match = regExp.firstMatch(contentDispositionHeader);\n          if (match != null && match.groupCount >= 1) {\n            name = match.group(1) ?? '';\n          }\n        }\n        if (profile case RemoteProfileEntity(:final url)) {\n          if (Uri.parse(url).fragment case final fragment when name.isEmpty) {\n            name = fragment;\n          }\n          if (url.split(\"/\").lastOrNull case final part? when name.isEmpty) {\n            final pattern = RegExp(r\"\\.(json|yaml|yml|txt)[\\s\\S]*\");\n            name = part.replaceFirst(pattern, \"\");\n          }\n        }\n        if (name.isBlank) {\n          switch (profile) {\n            case RemoteProfileEntity():\n              name = \"Remote Profile\";\n\n            case LocalProfileEntity():\n              name = protocol(File(tempFilePath).readAsStringSync());\n          }\n        }\n\n        if (headers['enable-warp'].toString() == 'true' || profile.userOverride?.enableWarp == true) {\n          final value = {'enable': true, 'mode': 'warp_over_proxy'};\n          headers['warp'] = value;\n          headers['warp2'] = value;\n        }\n\n        if (headers['enable-fragment'].toString() == 'true' || profile.userOverride?.enableFragment == true) {\n          headers['tls-tricks'] = {'enable-fragment': true};\n        }\n\n        final isAutoUpdateDisable = profile.userOverride?.isAutoUpdateDisable ?? false;\n        ProfileOptions? options;\n        if (profile.userOverride?.updateInterval case final int updateInterval\n            when updateInterval > 0 && !isAutoUpdateDisable) {\n          options = ProfileOptions(updateInterval: Duration(hours: updateInterval));\n        }\n        if (headers['profile-update-interval'] case final String updateIntervalStr\n            when options == null && !isAutoUpdateDisable) {\n          final updateInterval = Duration(hours: int.parse(updateIntervalStr));\n          options = ProfileOptions(updateInterval: updateInterval);\n        }\n\n        SubscriptionInfo? subInfo;\n        if (headers['subscription-userinfo'] case final String subInfoStr) {\n          subInfo = _parseSubscriptionInfo(subInfoStr);\n        }\n\n        if (subInfo != null) {\n          if (headers['profile-web-page-url'] case final String profileWebPageUrl when isUrl(profileWebPageUrl)) {\n            subInfo = subInfo.copyWith(webPageUrl: profileWebPageUrl);\n          }\n          if (headers['support-url'] case final String profileSupportUrl when isUrl(profileSupportUrl)) {\n            subInfo = subInfo.copyWith(supportUrl: profileSupportUrl);\n          }\n        }\n\n        headers.removeWhere(\n          (key, value) => !allowedOverrideConfigs.contains(key) || value == null || value.toString().isEmpty,\n        );\n\n        final profileOverrideStr = jsonEncode({for (final key in headers.keys) key: headers[key]});\n\n        return profile.map(\n          remote: (rp) => rp.copyWith(\n            name: name,\n            lastUpdate: DateTime.now(),\n            options: options,\n            subInfo: subInfo,\n            profileOverride: profileOverrideStr,\n          ),\n          local: (lp) => lp.copyWith(name: name, lastUpdate: DateTime.now(), profileOverride: profileOverrideStr),\n        );\n      }, ProfileFailure.unexpected);\n\n  static String protocol(String content) {\n    if (content.contains(\"[Interface]\")) {\n      return ProxyType.wireguard.label;\n    }\n    final lines = content.split('\\n');\n    String? name;\n    for (final line in lines) {\n      final uri = Uri.tryParse(line);\n      if (uri == null) continue;\n      final fragment = uri.hasFragment ? Uri.decodeComponent(uri.fragment.split(\" -> \")[0]) : null;\n      name ??= switch (uri.scheme) {\n        'ss' => fragment ?? ProxyType.shadowsocks.label,\n        'ssconf' => fragment ?? ProxyType.shadowsocks.label,\n        'vmess' => ProxyType.vmess.label,\n        'vless' => fragment ?? ProxyType.vless.label,\n        'trojan' => fragment ?? ProxyType.trojan.label,\n        'tuic' => fragment ?? ProxyType.tuic.label,\n        'hy2' || 'hysteria2' => fragment ?? ProxyType.hysteria2.label,\n        'hy' || 'hysteria' => fragment ?? ProxyType.hysteria.label,\n        'ssh' => fragment ?? ProxyType.ssh.label,\n        'wg' => fragment ?? ProxyType.wireguard.label,\n        'awg' => fragment ?? ProxyType.awg.label,\n        'shadowtls' => fragment ?? ProxyType.shadowtls.label,\n        'mieru' => fragment ?? ProxyType.mieru.label,\n        'warp' => fragment ?? ProxyType.warp.label,\n        _ => null,\n      };\n    }\n    return name ?? ProxyType.unknown.label;\n  }\n\n  static Map<String, dynamic> applyProfileOverride(Map<String, dynamic> main, String? profileOverride) {\n    if (profileOverride == null) return main;\n    if (profileOverride.contains(\"{\")) {\n      final profileOverrideMap = jsonDecode(profileOverride) as Map<String, dynamic>;\n      return _mergeJson(main, profileOverrideMap);\n    } else {\n      return main;\n    }\n  }\n\n  static Map<String, dynamic> _mergeJson(Map<String, dynamic> main, Map<String, dynamic> override) {\n    override.forEach((key, value) {\n      if (main.containsKey(key)) {\n        if (main[key] is Map<String, dynamic> && value is Map<String, dynamic>) {\n          main[key] = _mergeJson(main[key] as Map<String, dynamic>, value);\n        } else {\n          main[key] = value;\n        }\n      } else {\n        main[key] = value;\n      }\n    });\n    return main;\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/data/profile_path_resolver.dart",
    "content": "import 'dart:io';\n\nimport 'package:path/path.dart' as p;\n\nclass ProfilePathResolver {\n  const ProfilePathResolver(this._workingDir);\n\n  final Directory _workingDir;\n\n  Directory get directory => Directory(p.join(_workingDir.path, \"configs\"));\n\n  File file(String fileName) {\n    return File(p.join(directory.path, \"$fileName.json\"));\n  }\n\n  File tempFile(String fileName) => file(\"$fileName.tmp\");\n}\n"
  },
  {
    "path": "lib/features/profile/data/profile_repository.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:drift/drift.dart';\nimport 'package:flutter/foundation.dart';\nimport 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/db/db.dart';\n\nimport 'package:hiddify/core/utils/exception_handler.dart';\nimport 'package:hiddify/features/profile/data/profile_data_mapper.dart';\nimport 'package:hiddify/features/profile/data/profile_data_source.dart';\nimport 'package:hiddify/features/profile/data/profile_parser.dart';\nimport 'package:hiddify/features/profile/data/profile_path_resolver.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/features/profile/model/profile_failure.dart';\nimport 'package:hiddify/features/profile/model/profile_sort_enum.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:uuid/uuid.dart';\n\nabstract interface class ProfileRepository {\n  TaskEither<ProfileFailure, Unit> init();\n  TaskEither<ProfileFailure, ProfileEntity?> getById(String id);\n  TaskEither<ProfileFailure, Unit> setAsActive(String id);\n  TaskEither<ProfileFailure, Unit> deleteById(String id, bool isActive);\n  Stream<Either<ProfileFailure, ProfileEntity?>> watchActiveProfile();\n  Stream<Either<ProfileFailure, bool>> watchHasAnyProfile();\n  Stream<Either<ProfileFailure, List<ProfileEntity>>> watchAll({\n    ProfilesSort sort = ProfilesSort.lastUpdate,\n    SortMode sortMode = SortMode.ascending,\n  });\n  TaskEither<ProfileFailure, Unit> upsertRemote(String url, {UserOverride? userOverride, CancelToken? cancelToken});\n  TaskEither<ProfileFailure, Unit> addLocal(String content, {UserOverride? userOverride});\n  TaskEither<ProfileFailure, Unit> offlineUpdate(ProfileEntity nProfile, String nContent);\n  TaskEither<ProfileFailure, Unit> validateConfig(String path, String tempPath, String? profileOverride, bool debug);\n  TaskEither<ProfileFailure, String> generateConfig(String id);\n  TaskEither<ProfileFailure, String> getRawConfig(String id);\n}\n\nclass ProfileRepositoryImpl with ExceptionHandler, InfraLogger implements ProfileRepository {\n  ProfileRepositoryImpl({\n    required ProfileDataSource profileDataSource,\n    required ProfilePathResolver profilePathResolver,\n    required HiddifyCoreService singbox,\n    required ConfigOptionRepository configOptionRepository,\n    required ProfileParser profileParser,\n  }) : _profileParser = profileParser,\n       _configOptionRepo = configOptionRepository,\n       _singbox = singbox,\n       _profilePathResolver = profilePathResolver,\n       _profileDataSource = profileDataSource;\n\n  final ProfileDataSource _profileDataSource;\n  final ProfilePathResolver _profilePathResolver;\n  final HiddifyCoreService _singbox;\n  final ConfigOptionRepository _configOptionRepo;\n  final ProfileParser _profileParser;\n\n  @override\n  TaskEither<ProfileFailure, Unit> init() {\n    return exceptionHandler(() async {\n      if (!kIsWeb) {\n        if (!await _profilePathResolver.directory.exists()) {\n          await _profilePathResolver.directory.create(recursive: true);\n        }\n      }\n\n      return right(unit);\n    }, ProfileUnexpectedFailure.new);\n  }\n\n  @override\n  TaskEither<ProfileFailure, ProfileEntity?> getById(String id) {\n    return TaskEither.tryCatch(\n      () => _profileDataSource.getById(id).then((value) => value?.toEntity()),\n      ProfileUnexpectedFailure.new,\n    );\n  }\n\n  @override\n  TaskEither<ProfileFailure, Unit> setAsActive(String id) {\n    return TaskEither.tryCatch(() async {\n      await _profileDataSource.edit(id, const ProfileEntriesCompanion(active: Value(true)));\n      return unit;\n    }, ProfileUnexpectedFailure.new);\n  }\n\n  @override\n  TaskEither<ProfileFailure, Unit> deleteById(String id, bool isActive) {\n    return TaskEither.tryCatch(() async {\n      await _profileDataSource.deleteById(id, isActive);\n      await _profilePathResolver.file(id).delete();\n      return unit;\n    }, ProfileUnexpectedFailure.new);\n  }\n\n  @override\n  Stream<Either<ProfileFailure, ProfileEntity?>> watchActiveProfile() {\n    return _profileDataSource.watchActiveProfile().map((event) => event?.toEntity()).handleExceptions((\n      error,\n      stackTrace,\n    ) {\n      loggy.error(\"error watching active profile\", error, stackTrace);\n      return ProfileUnexpectedFailure(error, stackTrace);\n    });\n  }\n\n  @override\n  Stream<Either<ProfileFailure, bool>> watchHasAnyProfile() {\n    return _profileDataSource\n        .watchProfilesCount()\n        .map((event) => event != 0)\n        .handleExceptions(ProfileUnexpectedFailure.new);\n  }\n\n  @override\n  Stream<Either<ProfileFailure, List<ProfileEntity>>> watchAll({\n    ProfilesSort sort = ProfilesSort.lastUpdate,\n    SortMode sortMode = SortMode.ascending,\n  }) {\n    return _profileDataSource\n        .watchAll(sort: sort, sortMode: sortMode)\n        .map((event) => event.map((e) => e.toEntity()).toList())\n        .handleExceptions(ProfileUnexpectedFailure.new);\n  }\n\n  @override\n  TaskEither<ProfileFailure, Unit> upsertRemote(String url, {UserOverride? userOverride, CancelToken? cancelToken}) =>\n      TaskEither.tryCatch(\n        () async => await _profileDataSource.getByUrl(url).then((profEntry) => profEntry?.toEntity()),\n        ProfileFailure.unexpected,\n      ).flatMap((profEntity) {\n        // if profile is null, generate id\n        final id = profEntity?.id ?? const Uuid().v4();\n        final file = _profilePathResolver.file(id);\n        final tempFile = _profilePathResolver.tempFile(id);\n        try {\n          if (profEntity != null && profEntity is RemoteProfileEntity) {\n            // Update\n            if (userOverride != null) {\n              profEntity = profEntity.copyWith(userOverride: userOverride);\n            }\n            return _profileParser\n                .updateRemote(rp: profEntity, tempFilePath: tempFile.path, cancelToken: cancelToken)\n                .flatMap(\n                  (profEntity) =>\n                      validateConfig(file.path, tempFile.path, profEntity.profileOverride.value, false).flatMap(\n                        (unit) => TaskEither.tryCatch(() async {\n                          await _profileDataSource.edit(id, profEntity);\n                          return unit;\n                        }, ProfileFailure.unexpected),\n                      ),\n                );\n          } else {\n            // Add\n            return _profileParser\n                .addRemote(\n                  id: id,\n                  url: url,\n                  tempFilePath: tempFile.path,\n                  userOverride: userOverride,\n                  cancelToken: cancelToken,\n                )\n                .flatMap(\n                  (profEntity) =>\n                      validateConfig(file.path, tempFile.path, profEntity.profileOverride.value, false).flatMap(\n                        (unit) => TaskEither.tryCatch(() async {\n                          await _profileDataSource.insert(profEntity);\n                          return unit;\n                        }, ProfileFailure.unexpected),\n                      ),\n                );\n          }\n        } finally {\n          if (tempFile.existsSync()) tempFile.deleteSync();\n        }\n      });\n\n  @override\n  TaskEither<ProfileFailure, Unit> addLocal(String content, {UserOverride? userOverride}) =>\n      TaskEither.tryCatch(() async {\n        final id = const Uuid().v4();\n        final file = _profilePathResolver.file(id);\n        final tempFile = _profilePathResolver.tempFile(id);\n        try {\n          await tempFile.writeAsString(content);\n          final task = _profileParser\n              .addLocal(id: id, content: content, tempFilePath: tempFile.path, userOverride: userOverride)\n              .flatMap(\n                (profEntity) =>\n                    validateConfig(file.path, tempFile.path, profEntity.profileOverride.value, false).flatMap(\n                      (unit) => TaskEither.tryCatch(() async {\n                        await _profileDataSource.insert(profEntity);\n                        return unit;\n                      }, ProfileFailure.unexpected),\n                    ),\n              );\n          return (await task.run()).getOrElse((l) => throw l);\n        } finally {\n          if (tempFile.existsSync()) tempFile.deleteSync();\n        }\n      }, ProfileFailure.unexpected);\n\n  @override\n  TaskEither<ProfileFailure, Unit> offlineUpdate(ProfileEntity profile, String nContent) =>\n      TaskEither.tryCatch(\n        () async => await _profileDataSource.getById(profile.id).then((profEntry) => profEntry?.toEntity()),\n        ProfileFailure.unexpected,\n      ).flatMap((oProfile) {\n        if (oProfile == null || oProfile.runtimeType != profile.runtimeType) throw const ProfileFailure.notFound();\n        if (profile.userOverride == null) loggy.warning('Updaing profile content with \"userOverride\" == null');\n        final id = oProfile.id;\n        final file = _profilePathResolver.file(id);\n        final tempFile = _profilePathResolver.tempFile(id);\n        try {\n          return TaskEither.tryCatch(\n            () async => await tempFile.writeAsString(nContent),\n            ProfileFailure.unexpected,\n          ).flatMap(\n            (_) =>\n                TaskEither.fromEither(\n                  _profileParser.offlineUpdate(\n                    profile: oProfile.copyWith(userOverride: profile.userOverride),\n                    tempFilePath: tempFile.path,\n                  ),\n                ).flatMap(\n                  (profEntity) =>\n                      validateConfig(file.path, tempFile.path, profEntity.profileOverride.value, false).flatMap(\n                        (unit) => TaskEither.tryCatch(() async {\n                          await _profileDataSource.edit(id, profEntity);\n                          return unit;\n                        }, ProfileFailure.unexpected),\n                      ),\n                ),\n          );\n        } finally {\n          if (tempFile.existsSync()) tempFile.deleteSync();\n        }\n      });\n\n  @override\n  TaskEither<ProfileFailure, Unit> validateConfig(String path, String tempPath, String? profileOverride, bool debug) =>\n      TaskEither.fromEither(_configOptionRepo.fullOptionsOverrided(profileOverride))\n          .mapLeft((configOptionFailure) => ProfileFailure.invalidConfig(null, configOptionFailure))\n          .flatMap(\n            (overridedOptions) => _singbox\n                .changeOptions(overridedOptions)\n                .mapLeft(ProfileFailure.invalidConfig)\n                .flatMap(\n                  (_) => _singbox.validateConfigByPath(path, tempPath, debug).mapLeft(ProfileFailure.invalidConfig),\n                ),\n          );\n\n  @override\n  TaskEither<ProfileFailure, String> generateConfig(String id) => TaskEither.fromEither(\n    Either.tryCatch(() => _profilePathResolver.file(id), ProfileFailure.unexpected),\n  ).flatMap((configFile) => _singbox.generateFullConfigByPath(configFile.path).mapLeft(ProfileFailure.unexpected));\n\n  @override\n  TaskEither<ProfileFailure, String> getRawConfig(String id) {\n    return TaskEither.fromEither(\n      Either.tryCatch(() => _profilePathResolver.file(id), ProfileFailure.unexpected),\n    ).flatMap((configFile) => TaskEither.tryCatch(() => configFile.readAsString(), ProfileFailure.unexpected));\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/details/json_editor.dart",
    "content": "library json_editor_flutter;\n\nimport 'dart:convert';\nimport 'dart:async';\nimport 'dart:math';\nimport 'dart:ui';\n\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\n\nconst _space = 18.0;\nconst _textStyle = TextStyle(fontSize: 16);\nconst _options = Icon(Icons.more_horiz, size: 16);\nconst _expandIconWidth = 10.0;\nconst _rowHeight = 30.0;\nconst _popupMenuHeight = 30.0;\nconst _popupMenuItemPadding = 20.0;\nconst _textSpacer = SizedBox(width: 5);\nconst _newKey = \"new_key_added\";\nconst _downArrow = SizedBox(width: _expandIconWidth, child: Icon(FontAwesomeIcons.caretDown, size: 14));\nconst _rightArrow = SizedBox(width: _expandIconWidth, child: Icon(FontAwesomeIcons.caretRight, size: 14));\nconst _newDataValue = {\"string\": \"\", \"bool\": false, \"num\": 0};\nbool _enableMoreOptions = true;\nbool _enableKeyEdit = true;\nbool _enableValueEdit = true;\n\n// enum _OptionItems { map, list, string, bool, num, delete, protocols, configElement }\ntypedef _OptionItems = String;\n\nenum _SearchActions { next, prev }\n\n/// Supported editors for JSON Editor.\nenum Editors { tree, text }\n\nconst Map<String, Map<String, dynamic>> protocolSchemaValues = {\n  \"xray\": {\n    \"type\": \"xray\",\n    \"tag\": \"xray-out\",\n    \"xray_outbound_raw\": {},\n    \"xray_fragment\": {\"packets\": \"tlshello\", \"interval\": \"1-10\", \"length\": \"1-10\"},\n  },\n  \"warp\": {\n    \"type\": \"warp\",\n    \"key\": \"\",\n    \"host\": \"\",\n    \"port\": 808,\n    \"noise\": {\n      \"fake_packets\": {\"enabled\": true, \"count\": \"1-10\", \"delay\": \"1-10\", \"mode\": \"m4\"},\n    },\n  },\n  \"mieru\": {\n    \"type\": \"mieru\",\n    \"tag\": \"mieru-out\",\n    \"server\": \"127.0.0.1\",\n    \"portBindings\": [\n      {\"protocol\": \"tcp\", \"port\": 1080},\n      {\"protocol\": \"udp\", \"portRanges\": \"1080-1090\"},\n    ],\n    \"multiplexing\": \"high\",\n    \"handshake\": \"no_wait\",\n  },\n  \"naive\": {\n    \"type\": \"naive\",\n    \"tag\": \"naive-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"username\": \"\",\n    \"password\": \"\",\n    \"tls\": {\"enabled\": true},\n  },\n  \"dnstt\": {\n    \"type\": \"dnstt\",\n    \"tag\": \"dnstt-out\",\n    \"domain\": \"dnstt.hiddify.com\",\n    \"publicKey\": \"publickey\",\n    \"resolvers\": [\"8.8.8.8:53\", \"8.8.4.4:53\"],\n    \"tunnel_per_resolver\": 4,\n  },\n  \"vless\": {\n    \"type\": \"vless\",\n    \"tag\": \"vless-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"uuid\": \"bf000d23-0752-40b4-affe-68f7707a9661\",\n    \"flow\": \"xtls-rprx-vision\",\n    \"packet_encoding\": \"\",\n  },\n  \"vmess\": {\n    \"type\": \"vmess\",\n    \"tag\": \"vmess-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"uuid\": \"bf000d23-0752-40b4-affe-68f7707a9661\",\n    \"security\": \"auto\",\n    \"global_padding\": false,\n    \"authenticated_length\": true,\n    \"packet_encoding\": \"\",\n  },\n  \"trojan\": {\n    \"type\": \"trojan\",\n    \"tag\": \"trojan-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"password\": \"8JCsPssfgS8tiRwiMlhARg==\",\n  },\n  \"hysteria\": {\n    \"type\": \"hysteria\",\n    \"tag\": \"hysteria-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"up\": \"100 Mbps\",\n    \"up_mbps\": 100,\n    \"down\": \"100 Mbps\",\n    \"down_mbps\": 100,\n    \"obfs\": \"daylight\",\n    \"auth\": \"\",\n    \"auth_str\": \"password\",\n    \"recv_window_conn\": 0,\n    \"recv_window\": 0,\n    \"disable_mtu_discovery\": false,\n    \"tls\": {\"enabled\": true},\n  },\n  \"hysteria2\": {\n    \"type\": \"hysteria2\",\n    \"tag\": \"hy2-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"up_mbps\": 100,\n    \"down_mbps\": 100,\n    \"obfs\": {\"type\": \"salamander\", \"password\": \"cry_me_a_r1ver\"},\n    \"password\": \"goofy_ahh_password\",\n    \"tls\": {\"enabled\": true},\n  },\n  \"shadowsocks\": {\n    \"type\": \"shadowsocks\",\n    \"tag\": \"ss-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"method\": \"2022-blake3-aes-128-gcm\",\n    \"password\": \"8JCsPssfgS8tiRwiMlhARg==\",\n    \"plugin\": \"\",\n    \"plugin_opts\": \"\",\n    \"udp_over_tcp\": false,\n  },\n  \"socks\": {\n    \"type\": \"socks\",\n    \"tag\": \"socks-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"version\": \"5\",\n    \"username\": \"\",\n    \"password\": \"\",\n    \"udp_over_tcp\": false,\n  },\n  \"http\": {\n    \"type\": \"http\",\n    \"tag\": \"http-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"username\": \"\",\n    \"password\": \"\",\n    \"path\": \"\",\n    \"headers\": {},\n    \"tls\": {\"enabled\": false},\n  },\n  \"wireguard\": {\n    \"type\": \"wireguard\",\n    \"tag\": \"wireguard-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"system_interface\": false,\n    \"gso\": false,\n    \"interface_name\": \"wg0\",\n    \"local_address\": [\"10.0.0.2/32\"],\n    \"private_key\": \"YNXtAzepDqRv9H52osJVDQnznT5AM11eCK3ESpwSt04=\",\n    \"peer_public_key\": \"Z1XXLsKYkYxuiYjJIkRvtIKFepCYHTgON+GwPq7SOV4=\",\n    \"pre_shared_key\": \"31aIhAPwktDGpH4JDhA8GNvjFXEf/a6+UaQRyOAiyfM=\",\n    \"reserved\": [0, 0, 0],\n    \"workers\": 4,\n    \"mtu\": 1408,\n    \"fake_packets\": \"1-10\",\n    \"fake_packets_size\": \"1-10\",\n    \"fake_packets_delay\": \"1-10\",\n    \"fake_packets_mode\": \"m4\",\n  },\n  \"tuic\": {\n    \"type\": \"tuic\",\n    \"tag\": \"tuic-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 1080,\n    \"uuid\": \"2DD61D93-75D8-4DA4-AC0E-6AECE7EAC365\",\n    \"password\": \"hello\",\n    \"congestion_control\": \"cubic\",\n    \"udp_relay_mode\": \"native\",\n    \"udp_over_stream\": false,\n    \"zero_rtt_handshake\": false,\n    \"heartbeat\": \"10s\",\n    \"tls\": {\"enabled\": true},\n  },\n  \"ssh\": {\n    \"type\": \"ssh\",\n    \"tag\": \"ssh-out\",\n    \"server\": \"127.0.0.1\",\n    \"server_port\": 22,\n    \"user\": \"root\",\n    \"password\": \"admin\",\n    \"private_key\": \"\",\n    \"private_key_passphrase\": \"\",\n    \"host_key\": [\"\"],\n    \"client_version\": \"SSH-2.0-OpenSSH_7.4p1\",\n  },\n};\nconst Map<String, Map<String, Map<String, dynamic>>> exampleSchemaValues = {\n  \"config.outbounds.transport\": {\n    \"browser user-agent\": {\n      \"header\": {\"user-agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0\"},\n    },\n  },\n  \"config.outbounds.tls\": {\n    \"fragment\": {\n      \"tls_fragment\": {\"enabled\": true, \"size\": \"1-10\", \"sleep\": \"1-10\"},\n    },\n    \"utls\": {\n      \"utls\": {\"enabled\": true, \"fingerprint\": \"chrome\"},\n    },\n  },\n  \"config.outbounds\": {\n    \"multiplex\": {\n      \"multiplex\": {\n        \"enabled\": true,\n        \"protocol\": \"smux\",\n        \"max_connections\": 4,\n        \"min_streams\": 4,\n        \"max_streams\": 0,\n        \"padding\": false,\n        \"brutal\": {\"enabled\": true, \"up_mbps\": 100, \"down_mbps\": 100},\n      },\n    },\n    \"reality\": {\n      \"tls\": {\n        \"enabled\": true,\n        \"server_name\": \"\",\n        \"min_version\": \"\",\n        \"max_version\": \"\",\n        \"utls\": {\"enabled\": true, \"fingerprint\": \"chrome\"},\n        \"reality\": {\"enabled\": true, \"public_key\": \"\", \"short_id\": \"\"},\n      },\n    },\n    \"tls\": {\n      \"tls\": {\n        \"enabled\": true,\n        \"utls\": {\"enabled\": true, \"fingerprint\": \"chrome\"},\n        \"disable_sni\": false,\n        \"insecure\": false,\n        \"server_name\": \"\",\n        \"alpn\": [],\n        \"min_version\": \"\",\n        \"max_version\": \"\",\n        \"tls_fragment\": {\"enabled\": false, \"size\": \"1-10\", \"sleep\": \"1-10\"},\n      },\n    },\n    \"websocket\": {\n      \"transport\": {\"type\": \"ws\", \"path\": \"\", \"headers\": {}, \"max_early_data\": 0, \"early_data_header_name\": \"\"},\n    },\n    \"grpc\": {\n      \"transport\": {\n        \"type\": \"grpc\",\n        \"service_name\": \"TunService\",\n        \"idle_timeout\": \"15s\",\n        \"ping_timeout\": \"15s\",\n        \"permit_without_stream\": false,\n      },\n    },\n    \"quic\": {\n      \"transport\": {\"type\": \"quic\"},\n    },\n    \"http\": {\n      \"transport\": {\n        \"type\": \"http\",\n        \"host\": [],\n        \"path\": \"\",\n        \"method\": \"\",\n        \"headers\": {},\n        \"idle_timeout\": \"15s\",\n        \"ping_timeout\": \"15s\",\n      },\n    },\n    \"httpupgrade\": {\n      \"transport\": {\"type\": \"httpupgrade\", \"host\": \"\", \"path\": \"\", \"headers\": {}},\n    },\n    \"xhttp\": {\n      \"transport\": {\"type\": \"xhttp\", \"host\": \"\", \"path\": \"\", \"headers\": {}},\n    },\n  },\n};\n\nconst Map<String, List<String>> possibleValues = {\n  \"config.outbounds.flow\": <String>[\"\", \"xtls-rprx-vision\"],\n  \"config.outbounds.security\": <String>[\"\", \"auto\", \"none\", \"zero\", \"aes-128-gcm\", \"chacha20-poly1305\"],\n  \"config.outbounds.method\": <String>[\n    \"\",\n    \"2022-blake3-aes-128-gcm\",\n    \"2022-blake3-aes-256-gcm\",\n    \"2022-blake3-chacha20-poly1305\",\n    \"none\",\n    \"aes-128-gcm\",\n    \"aes-192-gcm\",\n    \"aes-256-gcm\",\n    \"chacha20-ietf-poly1305\",\n    \"xchacha20-ietf-poly1305\",\n  ],\n  \"config.outbounds.plugin\": <String>[\"\", \"obfs-local\", \"v2ray-plugin\"],\n  \"config.outbounds.network\": <String>[\"\", \"udp\", \"tcp\"],\n  \"config.endpoints.network\": <String>[\"\", \"udp\", \"tcp\"],\n  \"config.outbounds.multiplex.protocol\": <String>[\"\", \"smux\", \"yamux\", \"h2mux\"],\n  \"config.outbounds.tls.min_version\": <String>[\"\", \"1.0\", \"1.1\", \"1.2\", \"1.3\"],\n  \"config.outbounds.tls.max_version\": <String>[\"\", \"1.0\", \"1.1\", \"1.2\", \"1.3\"],\n  \"config.outbounds.tls.utls.fingerprint\": <String>[\n    \"\",\n    \"chrome\",\n    \"chrome_psk\",\n    \"chrome_psk_shuffle\",\n    \"chrome_padding_psk_shuffle\",\n    \"chrome_pq\",\n    \"chrome_pq_psk\",\n    \"firefox\",\n    \"edge\",\n    \"safari\",\n    \"360\",\n    \"qq\",\n    \"ios\",\n    \"android\",\n    \"random\",\n    \"randomized\",\n  ],\n  \"config.outbounds.packet_encoding\": <String>[\"\", \"(none)\", \"xudp\", \"packetaddr\"],\n  \"config.outbounds.transport.type\": <String>[\"\", \"http\", \"ws\", \"grpc\", \"quic\", \"httpupgrade\"],\n  \"config.outbounds.type\": <String>[\n    \"vless\",\n    \"dnstt\",\n    \"vmess\",\n    \"trojan\",\n    \"xray\",\n    \"shadowsocks\",\n    \"wireguard\",\n    \"hysteria\",\n    \"hysteria2\",\n    \"tuic\",\n    \"ssh\",\n    \"shadowtls\",\n    \"custom\",\n    \"direct\",\n    \"block\",\n    \"socks\",\n    \"http\",\n    \"mieru\",\n    \"naive\",\n    \"anytls\",\n  ],\n  \"config.endpoints.type\": <String>[\"wireguard\", \"warp\"],\n};\n\n/// Edit your JSON object with this Widget. Create, edit and format objects\n/// using this user friendly widget.\nclass JsonEditor extends StatefulWidget {\n  /// JSON can be edited in two ways, Tree editor or text editor. You can disable\n  /// either of them.\n  ///\n  /// When UI editor is active, you can disable adding/deleting keys by using\n  /// [enableMoreOptions]. Editing keys and values can also be disabled by using\n  /// [enableKeyEdit] and [enableValueEdit].\n  ///\n  /// When text editor is active, it will simply ignore [enableMoreOptions],\n  /// [enableKeyEdit] and [enableValueEdit].\n  ///\n  /// [duration] is the debounce time for [onChanged] function. Defaults to\n  /// 500 milliseconds.\n  ///\n  /// [editors] is the supported list of editors. First element will be\n  /// used as default editor. Defaults to `[Editors.tree, Editors.text]`.\n  const JsonEditor({\n    super.key,\n    required this.json,\n    required this.onChanged,\n    this.duration = const Duration(milliseconds: 500),\n    this.enableMoreOptions = true,\n    this.enableKeyEdit = true,\n    this.enableValueEdit = true,\n    this.editors = const [Editors.tree, Editors.text],\n    this.themeColor,\n    this.actions = const [],\n    this.enableHorizontalScroll = false,\n    this.searchDuration = const Duration(milliseconds: 500),\n    this.hideEditorsMenuButton = false,\n    this.expandedObjects = const [],\n  }) : assert(editors.length > 0, \"editors list cannot be empty\");\n\n  /// JSON string to be edited.\n  final String json;\n\n  /// Callback function that will be called with the new [dynamic] data.\n  final ValueChanged<dynamic> onChanged;\n\n  /// Debounce duration for [onChanged] function.\n  final Duration duration;\n\n  /// Enables more options like adding or deleting data. Defaults to `true`.\n  final bool enableMoreOptions;\n\n  /// Enables editing of keys. Defaults to `true`.\n  final bool enableKeyEdit;\n\n  /// Enables editing of values. Defaults to `true`.\n  final bool enableValueEdit;\n\n  /// Theme color for the editor. Changes the border color and header color.\n  final Color? themeColor;\n\n  /// List of supported editors. First element will be used as default editor.\n  final List<Editors> editors;\n\n  /// A list of Widgets to display in a row at the end of header.\n  final List<Widget> actions;\n\n  /// Enables horizontal scroll for the tree view. Defaults to `false`.\n  final bool enableHorizontalScroll;\n\n  /// Debounce duration for search function.\n  final Duration searchDuration;\n\n  /// Hides the option of changing editor. Defaults to `false`.\n  final bool hideEditorsMenuButton;\n\n  /// [expandedObjects] refers to the objects that will be expanded by\n  /// default. Index can be provided when the data is a List.\n  ///\n  /// Examples:\n  /// ```dart\n  /// data = {\n  ///   \"hobbies\": [\"Reading books\", \"Playing Cricket\"],\n  ///   \"education\": [\n  ///     {\"name\": \"Bachelor of Engineering\", \"marks\": 75},\n  ///     {\"name\": \"Master of Engineering\", \"marks\": 72},\n  ///   ],\n  /// }\n  /// ```\n  ///\n  /// For the given data\n  /// 1. To expand education pass => `[\"education\"]`\n  /// 2. To expand hobbies and education pass => `[\"hobbies\", \"education\"]`\n  /// 3. To expand the first element (index 0) of education list, this means\n  /// we need to expand education too. In this case you need not to pass\n  /// \"education\" separately. Just pass a list of all nested objects =>\n  /// `[[\"education\", 0]]`\n  ///\n  /// ```dart\n  /// JsonEditor(\n  ///   expandedObjects: const [\n  ///     \"hobbies\",\n  ///     [\"education\", 0] // expands nested object in education\n  ///   ],\n  ///   onChanged: (_) {},\n  ///   json: jsonEncode(data),\n  /// )\n  /// ```\n  final List expandedObjects;\n\n  @override\n  State<JsonEditor> createState() => _JsonEditorState();\n}\n\nclass _JsonEditorState extends State<JsonEditor> {\n  Timer? _timer;\n  Timer? _searchTimer;\n  late dynamic _data;\n  late final _themeColor = widget.themeColor ?? Theme.of(context).primaryColor;\n  late Editors _editor = widget.editors.first;\n  bool _onError = false;\n  bool? allExpanded;\n  late final _controller = TextEditingController()..text = _stringifyData(_data, 0, true);\n  late final _scrollController = ScrollController();\n  final _matchedKeys = <String, bool>{};\n  final _matchedKeysLocation = <List>[];\n  int? _focusedKey;\n  int? _results;\n  late final _expandedObjects = <String, bool>{\n    [\"config\"].toString(): true,\n    if (widget.expandedObjects.isNotEmpty) ...getExpandedParents(),\n  };\n\n  Map<String, bool> getExpandedParents() {\n    final map = <String, bool>{};\n    for (var key in widget.expandedObjects) {\n      if (key is List) {\n        final newExpandList = [\"config\", ...key];\n        for (int i = newExpandList.length - 1; i > 0; i--) {\n          map[newExpandList.toString()] = true;\n          newExpandList.removeLast();\n        }\n      } else {\n        map[[\"config\", key].toString()] = true;\n      }\n    }\n    return map;\n  }\n\n  void callOnChanged() {\n    if (_timer?.isActive ?? false) _timer?.cancel();\n\n    _timer = Timer(widget.duration, () {\n      widget.onChanged(jsonDecode(jsonEncode(_data)));\n    });\n  }\n\n  void parseData(String value) {\n    if (_timer?.isActive ?? false) _timer?.cancel();\n\n    _timer = Timer(widget.duration, () {\n      try {\n        _data = jsonDecode(value);\n        widget.onChanged(_data);\n        setState(() {\n          _onError = false;\n        });\n      } catch (_) {\n        setState(() {\n          _onError = true;\n        });\n      }\n    });\n  }\n\n  void copyData() async {\n    await Clipboard.setData(ClipboardData(text: const JsonEncoder.withIndent(' ').convert(_data)));\n  }\n\n  bool updateParentObjects(List newExpandList) {\n    bool needsRebuilding = false;\n    for (int i = newExpandList.length - 1; i >= 0; i--) {\n      if (_expandedObjects[newExpandList.toString()] == null) {\n        _expandedObjects[newExpandList.toString()] = true;\n        needsRebuilding = true;\n      }\n      newExpandList.removeLast();\n    }\n    return needsRebuilding;\n  }\n\n  void findMatchingKeys(data, String text, List nestedParents) {\n    if (data is Map) {\n      final keys = data.keys.toList();\n      for (var key in keys) {\n        final keyName = key.toString();\n        if (keyName.toLowerCase().contains(text) ||\n            (data[key] is String && data[key].toString().toLowerCase().contains(text))) {\n          _results = _results! + 1;\n          _matchedKeys[keyName] = true;\n          _matchedKeysLocation.add([...nestedParents, key]);\n        }\n        if (data[key] is Map) {\n          findMatchingKeys(data[key], text, [...nestedParents, key]);\n        } else if (data[key] is List) {\n          findMatchingKeys(data[key], text, [...nestedParents, key]);\n        }\n      }\n    } else if (data is List) {\n      for (int i = 0; i < data.length; i++) {\n        final item = data[i];\n        if (item is Map) {\n          findMatchingKeys(item, text, [...nestedParents, i]);\n        } else if (item is List) {\n          findMatchingKeys(item, text, [...nestedParents, i]);\n        }\n      }\n    }\n  }\n\n  void onSearch(String text) {\n    if (_searchTimer?.isActive ?? false) _searchTimer?.cancel();\n\n    _searchTimer = Timer(widget.searchDuration, () async {\n      _matchedKeys.clear();\n      _matchedKeysLocation.clear();\n      _focusedKey = null;\n      if (text.isEmpty) {\n        setState(() {\n          _results = null;\n        });\n      } else {\n        _results = 0;\n        findMatchingKeys(_data, text.toLowerCase(), [\"config\"]);\n        setState(() {});\n        if (_matchedKeys.isNotEmpty) {\n          _focusedKey = 0;\n          scrollTo(0);\n        }\n      }\n    });\n  }\n\n  int getOffset(List toFind) {\n    int offset = 1;\n    bool keyFound = false;\n\n    void calculateOffset(data, List parents, List toFind) {\n      if (keyFound) return;\n      if (data is Map) {\n        for (var entry in data.entries) {\n          if (keyFound) return;\n          offset++;\n          final newList = [...parents, entry.key];\n          if (entry.key == toFind.last && newList.toString() == toFind.toString()) {\n            keyFound = true;\n            return;\n          }\n          if (entry.value is Map || entry.value is List) {\n            if (_expandedObjects[newList.toString()] == true && !keyFound) {\n              calculateOffset(entry.value, newList, toFind);\n            }\n          }\n        }\n      } else if (data is List) {\n        for (int i = 0; i < data.length; i++) {\n          if (keyFound) return;\n          offset++;\n          if (data[i] is Map || data[i] is List) {\n            final newList = [...parents, i];\n            if (_expandedObjects[newList.toString()] == true && !keyFound) {\n              calculateOffset(data[i], newList, toFind);\n            }\n          }\n        }\n      }\n    }\n\n    calculateOffset(_data, [\"config\"], toFind);\n    return offset;\n  }\n\n  void scrollTo(int index) {\n    final toFind = [..._matchedKeysLocation[index]];\n    final needsRebuilding = updateParentObjects([..._matchedKeysLocation[index]]..removeLast());\n    if (needsRebuilding) setState(() {});\n    Future.delayed(const Duration(milliseconds: 150), () {\n      _scrollController.animateTo(\n        (getOffset(toFind) * _rowHeight) - 90,\n        duration: const Duration(milliseconds: 200),\n        curve: Curves.easeInOut,\n      );\n    });\n  }\n\n  void onSearchAction(_SearchActions action) {\n    if (_matchedKeys.isEmpty) return;\n    if (action == _SearchActions.next) {\n      if (_focusedKey != null && _matchedKeysLocation.length - 1 > _focusedKey!) {\n        _focusedKey = _focusedKey! + 1;\n      } else {\n        _focusedKey = 0;\n      }\n    } else {\n      if (_focusedKey != null && _focusedKey! > 0) {\n        _focusedKey = _focusedKey! - 1;\n      } else {\n        _focusedKey = _matchedKeysLocation.length - 1;\n      }\n    }\n    scrollTo(_focusedKey!);\n  }\n\n  void expandAllObjects(data, List expandedList) {\n    if (data is Map) {\n      for (var entry in data.entries) {\n        if (entry.value is Map || entry.value is List) {\n          final newList = [...expandedList, entry.key];\n          _expandedObjects[newList.toString()] = true;\n          expandAllObjects(entry.value, newList);\n        }\n      }\n    } else if (data is List) {\n      for (int i = 0; i < data.length; i++) {\n        if (data[i] is Map || data[i] is List) {\n          final newList = [...expandedList, i];\n          _expandedObjects[newList.toString()] = true;\n          expandAllObjects(data[i], newList);\n        }\n      }\n    }\n  }\n\n  Widget wrapWithHorizontolScroll(Widget child) {\n    if (widget.enableHorizontalScroll) {\n      return SingleChildScrollView(scrollDirection: Axis.horizontal, child: child);\n    }\n    return child;\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    _data = jsonDecode(widget.json);\n    _enableMoreOptions = widget.enableMoreOptions;\n    _enableKeyEdit = widget.enableKeyEdit;\n    _enableValueEdit = widget.enableValueEdit;\n  }\n\n  @override\n  void dispose() {\n    _timer?.cancel();\n    _controller.dispose();\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Directionality(\n      textDirection: TextDirection.ltr,\n      child: DecoratedBox(\n        decoration: BoxDecoration(\n          border: Border.all(width: _onError ? 2 : 1, color: _onError ? Colors.red : _themeColor),\n        ),\n        child: SizedBox(\n          child: Column(\n            crossAxisAlignment: CrossAxisAlignment.start,\n            children: [\n              DecoratedBox(\n                decoration: BoxDecoration(\n                  color: _themeColor,\n                  border: _onError ? const Border(bottom: BorderSide(color: Colors.red, width: 2)) : null,\n                ),\n                child: Padding(\n                  padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 10),\n                  child: Row(\n                    children: [\n                      const Text('Config Editor:  '),\n                      if (!widget.hideEditorsMenuButton)\n                        PopupMenuButton<Editors>(\n                          initialValue: _editor,\n                          tooltip: 'Change editor',\n                          padding: EdgeInsets.zero,\n                          onSelected: (value) {\n                            if (value == Editors.text) {\n                              _controller.text = _stringifyData(_data, 0, true);\n                            }\n                            setState(() {\n                              _editor = value;\n                            });\n                          },\n                          position: PopupMenuPosition.under,\n                          enabled: widget.editors.length > 1,\n                          constraints: const BoxConstraints(minWidth: 50, maxWidth: 150),\n                          itemBuilder: (context) {\n                            return <PopupMenuEntry<Editors>>[\n                              PopupMenuItem<Editors>(\n                                height: _popupMenuHeight,\n                                padding: const EdgeInsets.symmetric(horizontal: 12),\n                                enabled: widget.editors.contains(Editors.tree),\n                                value: Editors.tree,\n                                child: const Text(\"Tree\"),\n                              ),\n                              PopupMenuItem<Editors>(\n                                height: _popupMenuHeight,\n                                padding: const EdgeInsets.symmetric(horizontal: 12),\n                                enabled: widget.editors.contains(Editors.text),\n                                value: Editors.text,\n                                child: const Text(\"Text\"),\n                              ),\n                            ];\n                          },\n                          child: Row(\n                            mainAxisSize: MainAxisSize.min,\n                            children: [\n                              Text(_editor.name, style: _textStyle),\n                              const Icon(Icons.arrow_drop_down, size: 20),\n                            ],\n                          ),\n                        ),\n                      const Spacer(),\n                      if (_editor == Editors.text) ...[\n                        const SizedBox(width: 20),\n                        InkWell(\n                          onTap: () {\n                            _controller.text = _stringifyData(_data, 0, true);\n                          },\n                          child: const Tooltip(message: 'Format', child: Icon(Icons.format_align_left, size: 20)),\n                        ),\n                      ] else ...[\n                        const SizedBox(width: 20),\n                        if (_results != null) ...[Text(\"$_results results\"), const SizedBox(width: 5)],\n                        _SearchField(onSearch, onSearchAction),\n                        const SizedBox(width: 20),\n                        InkWell(\n                          onTap: () {\n                            _expandedObjects[[\"config\"].toString()] = true;\n                            expandAllObjects(_data, [\"config\"]);\n                            setState(() {});\n                          },\n                          child: const Tooltip(message: 'Expand All', child: Icon(Icons.expand, size: 20)),\n                        ),\n                        const SizedBox(width: 20),\n                        InkWell(\n                          onTap: () {\n                            _expandedObjects.clear();\n                            setState(() {});\n                          },\n                          child: const Tooltip(message: 'Collapse All', child: Icon(Icons.compress, size: 20)),\n                        ),\n                      ],\n                      const SizedBox(width: 20),\n                      InkWell(\n                        onTap: copyData,\n                        child: const Tooltip(message: 'Copy', child: Icon(Icons.copy, size: 20)),\n                      ),\n                      if (widget.actions.isNotEmpty) const SizedBox(width: 20),\n                      ...widget.actions,\n                    ],\n                  ),\n                ),\n              ),\n              if (_editor == Editors.tree)\n                Expanded(\n                  child: SingleChildScrollView(\n                    controller: _scrollController,\n                    physics: const ClampingScrollPhysics(),\n                    child: wrapWithHorizontolScroll(\n                      _Holder(\n                        key: UniqueKey(),\n                        data: _data,\n                        keyName: \"config\",\n                        paddingLeft: _space,\n                        onChanged: callOnChanged,\n                        parentObject: {\"config\": _data},\n                        setState: setState,\n                        matchedKeys: _matchedKeys,\n                        allParents: const [\"config\"],\n                        expandedObjects: _expandedObjects,\n                      ),\n                    ),\n                  ),\n                ),\n              if (_editor == Editors.text)\n                Expanded(\n                  child: TextFormField(\n                    style: _textStyle,\n                    controller: _controller,\n                    onChanged: parseData,\n                    maxLines: null,\n                    minLines: null,\n                    expands: true,\n                    textAlignVertical: TextAlignVertical.top,\n                    decoration: const InputDecoration(\n                      border: InputBorder.none,\n                      contentPadding: EdgeInsets.only(left: 5, top: 8, bottom: 8),\n                    ),\n                  ),\n                ),\n            ],\n          ),\n        ),\n      ),\n    );\n  }\n}\n\nclass _Holder extends StatefulWidget {\n  const _Holder({\n    super.key,\n    this.keyName,\n    required this.data,\n    required this.paddingLeft,\n    required this.onChanged,\n    required this.parentObject,\n    required this.setState,\n    required this.matchedKeys,\n    required this.allParents,\n    required this.expandedObjects,\n  });\n\n  final dynamic keyName;\n  final dynamic data;\n  final double paddingLeft;\n  final VoidCallback onChanged;\n  final dynamic parentObject;\n  final StateSetter setState;\n  final Map<String, bool> matchedKeys;\n  final List allParents;\n  final Map<String, bool> expandedObjects;\n  String getKeyPath() {\n    final basePath = allParents.whereType<String>().join('.');\n\n    // final typePath = (parentObject['type'] != null &&\n    //         parentObject['type'] != keyName)\n    //     ? '.${parentObject['type']}'\n    //     : '';\n\n    return '$basePath';\n  }\n\n  @override\n  State<_Holder> createState() => _HolderState();\n}\n\nclass _HolderState extends State<_Holder> {\n  late bool isExpanded = widget.expandedObjects[widget.allParents.toString()] == true;\n\n  void _toggleState() {\n    if (!isExpanded) {\n      widget.expandedObjects[widget.allParents.toString()] = true;\n    } else {\n      widget.expandedObjects.remove(widget.allParents.toString());\n    }\n    setState(() {\n      isExpanded = !isExpanded;\n    });\n  }\n\n  void onSelected(_OptionItems selectedItem) {\n    if (selectedItem == \"delete\") {\n      if (widget.parentObject is Map) {\n        widget.parentObject.remove(widget.keyName);\n      } else {\n        widget.parentObject.removeAt(widget.keyName);\n      }\n\n      widget.setState(() {});\n    } else if (selectedItem == \"map\") {\n      if (widget.data is Map) {\n        widget.data[_newKey] = Map<String, dynamic>();\n      } else {\n        widget.data.add(Map<String, dynamic>());\n      }\n\n      setState(() {});\n      widget.onChanged();\n    } else if (exampleSchemaValues.containsKey(selectedItem.split(\"___\")[0])) {\n      final jsonItem = exampleSchemaValues[selectedItem.split(\"___\")[0]]![selectedItem.split(\"___\")[1]]!;\n      for (final key in jsonItem.keys) {\n        widget.data[key] = jsonDecode(jsonEncode(jsonItem[key]));\n      }\n\n      setState(() {});\n    } else if (protocolSchemaValues.containsKey(selectedItem)) {\n      final jsonItem = protocolSchemaValues[selectedItem]!;\n      widget.data.add(jsonDecode(jsonEncode(jsonItem)));\n      setState(() {});\n    } else if (selectedItem == \"list\") {\n      if (widget.data is Map) {\n        widget.data[_newKey] = [];\n      } else {\n        widget.data.add([]);\n      }\n\n      setState(() {});\n    } else {\n      if (widget.data is Map) {\n        widget.data[_newKey] = _newDataValue[selectedItem];\n      } else {\n        widget.data.add(_newDataValue[selectedItem]);\n      }\n\n      setState(() {});\n    }\n\n    widget.onChanged();\n  }\n\n  void onKeyChanged(Object key) {\n    final val = widget.parentObject.remove(widget.keyName);\n    widget.parentObject[key] = val;\n\n    widget.onChanged();\n    widget.setState(() {});\n  }\n\n  void onValueChanged(Object value) {\n    widget.parentObject[widget.keyName] = value;\n\n    widget.onChanged();\n  }\n\n  Widget wrapWithColoredBox(Widget child, String key) {\n    if (widget.matchedKeys[key] == true) {\n      return ColoredBox(color: Theme.of(context).colorScheme.secondaryContainer, child: child);\n    }\n    return child;\n  }\n\n  String getChildSummary(_Holder widget) {\n    final data = widget.data;\n\n    var res = \"{\";\n    if (data is Map<String, dynamic>) {\n      if (widget.expandedObjects[widget.allParents.toString()] ?? false) return \"\";\n      final content = data as Map<String, dynamic>;\n      //res += \"${data.length}\";\n      if (content[\"type\"] != null) {\n        res += \"${content[\"type\"]}\";\n      }\n      if (content[\"tag\"] != null) {\n        res += \" [${content[\"tag\"]}]\";\n      } else {\n        final d = \"$content\";\n        res += \" [${d.substring(0, min(20, d.length))}...]\";\n      }\n    } else if (data is List) {\n      final content = data as List;\n      res += \"${content.length}\";\n    }\n    return res + \"}\";\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    if (widget.data is Map<String, dynamic>) {\n      final mapWidget = <Widget>[];\n      final widgetData = widget.data as Map<String, dynamic>;\n      final List<String> keys = widgetData.keys.toList();\n      for (var key in keys) {\n        mapWidget.add(\n          _Holder(\n            key: Key(key),\n            data: widget.data[key],\n            keyName: key,\n            onChanged: widget.onChanged,\n            parentObject: widget.data,\n            paddingLeft: widget.paddingLeft + _space,\n            setState: setState,\n            matchedKeys: widget.matchedKeys,\n            allParents: [...widget.allParents, key],\n            expandedObjects: widget.expandedObjects,\n          ),\n        );\n      }\n\n      return Column(\n        crossAxisAlignment: CrossAxisAlignment.start,\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          SizedBox(\n            height: _rowHeight,\n            child: Row(\n              children: [\n                const SizedBox(width: _expandIconWidth),\n                if (_enableMoreOptions) _Options<Map>(onSelected, widget.getKeyPath()),\n                SizedBox(width: widget.paddingLeft),\n                InkWell(\n                  hoverColor: Colors.transparent,\n                  splashColor: Colors.transparent,\n                  onTap: _toggleState,\n                  child: isExpanded ? _downArrow : _rightArrow,\n                ),\n                const SizedBox(width: _expandIconWidth),\n                if (_enableKeyEdit && widget.parentObject is! List) ...[\n                  _ReplaceTextWithField(\n                    key: Key(widget.keyName.toString()),\n                    initialValue: widget.keyName,\n                    isKey: true,\n                    onChanged: onKeyChanged,\n                    setState: setState,\n                    isHighlighted: widget.matchedKeys[\"${widget.keyName}\"] == true,\n                  ),\n                  _textSpacer,\n                  Text(getChildSummary(widget), style: _textStyle),\n                ] else\n                  InkWell(\n                    hoverColor: Colors.transparent,\n                    splashColor: Colors.transparent,\n                    onTap: _toggleState,\n                    child: Row(\n                      mainAxisSize: MainAxisSize.min,\n                      children: [\n                        wrapWithColoredBox(Text(\"${widget.keyName}\", style: _textStyle), \"${widget.keyName}\"),\n                        _textSpacer,\n                        Text(getChildSummary(widget), style: _textStyle),\n                      ],\n                    ),\n                  ),\n              ],\n            ),\n          ),\n          if (isExpanded)\n            Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: mapWidget),\n        ],\n      );\n    } else if (widget.data is List) {\n      final listWidget = <Widget>[];\n      final widgetData = widget.data as List;\n      for (int i = 0; i < widgetData.length; i++) {\n        listWidget.add(\n          _Holder(\n            key: Key(\"$i\"),\n            keyName: i,\n            data: widgetData[i],\n            onChanged: widget.onChanged,\n            parentObject: widget.data,\n            paddingLeft: widget.paddingLeft + _space,\n            setState: setState,\n            matchedKeys: widget.matchedKeys,\n            allParents: [...widget.allParents, i],\n            expandedObjects: widget.expandedObjects,\n          ),\n        );\n      }\n\n      return Column(\n        crossAxisAlignment: CrossAxisAlignment.start,\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          SizedBox(\n            height: _rowHeight,\n            child: Row(\n              mainAxisSize: MainAxisSize.min,\n              children: [\n                const SizedBox(width: _expandIconWidth),\n                if (_enableMoreOptions) _Options<List>(onSelected, widget.getKeyPath()),\n                SizedBox(width: widget.paddingLeft),\n                InkWell(\n                  hoverColor: Colors.transparent,\n                  splashColor: Colors.transparent,\n                  onTap: _toggleState,\n                  child: isExpanded ? _downArrow : _rightArrow,\n                ),\n                const SizedBox(width: _expandIconWidth),\n                if (_enableKeyEdit && widget.parentObject is! List) ...[\n                  _ReplaceTextWithField(\n                    key: Key(widget.keyName.toString()),\n                    initialValue: widget.keyName,\n                    isKey: true,\n                    onChanged: onKeyChanged,\n                    setState: setState,\n                    isHighlighted: widget.matchedKeys[\"${widget.keyName}\"] == true,\n                  ),\n                  _textSpacer,\n                  Text(\"[${widget.data.length}]\", style: _textStyle),\n                ] else\n                  InkWell(\n                    hoverColor: Colors.transparent,\n                    splashColor: Colors.transparent,\n                    onTap: _toggleState,\n                    child: Row(\n                      mainAxisSize: MainAxisSize.min,\n                      children: [\n                        wrapWithColoredBox(Text(\"${widget.keyName}\", style: _textStyle), \"${widget.keyName}\"),\n                        _textSpacer,\n                        Text(\"[${widget.data.length}]\", style: _textStyle),\n                      ],\n                    ),\n                  ),\n              ],\n            ),\n          ),\n          if (isExpanded)\n            Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: listWidget),\n        ],\n      );\n    } else {\n      return SizedBox(\n        height: _rowHeight,\n        child: Row(\n          mainAxisSize: MainAxisSize.min,\n          children: [\n            const SizedBox(width: _expandIconWidth),\n            if (_enableMoreOptions) _Options<String>(onSelected, widget.getKeyPath()),\n            SizedBox(width: widget.paddingLeft + (_expandIconWidth * 2)),\n            Row(\n              mainAxisSize: MainAxisSize.min,\n              children: [\n                if (_enableKeyEdit) ...[\n                  _ReplaceTextWithField(\n                    key: Key(widget.keyName.toString()),\n                    initialValue: widget.keyName,\n                    isKey: true,\n                    onChanged: onKeyChanged,\n                    setState: setState,\n                    isHighlighted: widget.matchedKeys[\"${widget.keyName}\"] == true,\n                  ),\n                  const Text(' :', style: _textStyle),\n                ] else\n                  Row(\n                    mainAxisSize: MainAxisSize.min,\n                    children: [\n                      wrapWithColoredBox(Text(\"${widget.keyName}\", style: _textStyle), \"${widget.keyName}\"),\n                      _textSpacer,\n                      const Text(\" :\", style: _textStyle),\n                    ],\n                  ),\n                _textSpacer,\n                if (_enableValueEdit) ...[\n                  _ReplaceTextWithField(\n                    key: UniqueKey(),\n                    initialValue: widget.data,\n                    keyPath: widget.getKeyPath(),\n                    onChanged: onValueChanged,\n                    setState: setState,\n                  ),\n                  _textSpacer,\n                ] else ...[\n                  Text(widget.data.toString(), style: _textStyle),\n                  _textSpacer,\n                ],\n              ],\n            ),\n          ],\n        ),\n      );\n    }\n  }\n}\n\nclass _ReplaceTextWithField extends StatefulWidget {\n  const _ReplaceTextWithField({\n    super.key,\n    required this.initialValue,\n    required this.onChanged,\n    required this.setState,\n    this.isKey = false,\n    this.isHighlighted = false,\n    this.keyPath = \"\",\n  });\n  final String keyPath;\n  final dynamic initialValue;\n  final bool isKey;\n  final ValueChanged<Object> onChanged;\n  final StateSetter setState;\n  final bool isHighlighted;\n\n  @override\n  State<_ReplaceTextWithField> createState() => _ReplaceTextWithFieldState();\n}\n\nclass _ReplaceTextWithFieldState extends State<_ReplaceTextWithField> {\n  late final _focusNode = FocusNode();\n  bool _isFocused = false;\n  bool _value = false;\n  String _text = \"\";\n  late final BoxConstraints _constraints;\n\n  void handleChange() {\n    if (!_focusNode.hasFocus) {\n      _text = _text.trim();\n      final val = num.tryParse(_text);\n      if (val == null) {\n        widget.onChanged(_text);\n      } else {\n        widget.onChanged(val);\n      }\n\n      setState(() {\n        _isFocused = false;\n      });\n    }\n  }\n\n  Widget wrapWithColoredBox(String keyName) {\n    if (widget.isHighlighted) {\n      return ColoredBox(\n        color: Theme.of(context).colorScheme.errorContainer,\n        child: Text(keyName, style: _textStyle),\n      );\n    }\n    return Text(keyName, style: _textStyle);\n  }\n\n  @override\n  void initState() {\n    super.initState();\n\n    if (widget.initialValue is bool) {\n      _value = widget.initialValue as bool;\n    } else {\n      if (widget.initialValue == _newKey) {\n        _text = \"\";\n        _isFocused = true;\n        _focusNode.requestFocus();\n      } else {\n        _text = widget.initialValue.toString();\n      }\n    }\n\n    if (widget.isKey) {\n      _constraints = const BoxConstraints(minWidth: 20, maxWidth: 100);\n    } else if (widget.initialValue is num) {\n      _constraints = const BoxConstraints(minWidth: 20, maxWidth: 80);\n    } else {\n      _constraints = const BoxConstraints(minWidth: 20, maxWidth: 400);\n    }\n\n    _focusNode.addListener(handleChange);\n  }\n\n  @override\n  void dispose() {\n    _focusNode.removeListener(handleChange);\n    _focusNode.dispose();\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    if (possibleValues.containsKey(widget.keyPath)) {\n      final options = possibleValues[widget.keyPath]!;\n      return Row(\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          Transform.scale(\n            scale: 0.75,\n            child: DropdownButton<String>(\n              hint: Text('Select ${widget.keyPath.replaceAll(\"config.outbounds\", \"\")}'),\n              value: _text,\n              icon: const Icon(Icons.arrow_downward),\n              iconSize: 24,\n              elevation: 16,\n              underline: Container(height: 2),\n              onChanged: (String? newValue) {\n                widget.onChanged(newValue!);\n                _text = newValue;\n                setState(() {\n                  _text = newValue;\n                });\n              },\n              items: options.map<DropdownMenuItem<String>>((String value) {\n                return DropdownMenuItem<String>(value: value, child: Text(value));\n              }).toList(),\n            ),\n          ),\n        ],\n      );\n    } else if (widget.initialValue is bool) {\n      return Row(\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          Transform.scale(\n            scale: 0.75,\n            child: Checkbox(\n              visualDensity: const VisualDensity(horizontal: -4, vertical: -4),\n              value: _value,\n              onChanged: (value) {\n                widget.onChanged(value!);\n                setState(() {\n                  _value = value;\n                });\n              },\n            ),\n          ),\n          Text(_value.toString(), style: _textStyle),\n        ],\n      );\n    } else {\n      if (_isFocused) {\n        return TextFormField(\n          initialValue: _text,\n          focusNode: _focusNode,\n          onChanged: (value) => _text = value,\n          autocorrect: false,\n          cursorWidth: 1,\n          style: _textStyle,\n          cursorHeight: 12,\n          decoration: InputDecoration(\n            constraints: _constraints,\n            border: InputBorder.none,\n            fillColor: Colors.transparent,\n            filled: true,\n            isDense: true,\n            contentPadding: const EdgeInsets.all(3),\n            focusedBorder: const OutlineInputBorder(\n              borderRadius: BorderRadius.zero,\n              borderSide: BorderSide(width: 0.3),\n            ),\n          ),\n        );\n      } else {\n        return InkWell(\n          onTap: () {\n            setState(() {\n              _isFocused = true;\n            });\n            _focusNode.requestFocus();\n          },\n          mouseCursor: WidgetStateMouseCursor.textable,\n          child: widget.initialValue is String && _text.isEmpty\n              ? const SizedBox(width: 400, height: 18)\n              : wrapWithColoredBox(_text),\n        );\n      }\n    }\n  }\n}\n\nclass _Options<T> extends StatelessWidget {\n  const _Options(this.onSelected, this.keyPath);\n  final String keyPath;\n  final void Function(_OptionItems) onSelected;\n\n  @override\n  Widget build(BuildContext context) {\n    return PopupMenuButton<_OptionItems>(\n      tooltip: 'Add new object',\n      padding: EdgeInsets.zero,\n      onSelected: onSelected,\n      itemBuilder: (context) {\n        return <PopupMenuEntry<_OptionItems>>[\n          if (keyPath != \"config\" && T == Map)\n            const _PopupMenuWidget(\n              Row(\n                mainAxisSize: MainAxisSize.min,\n                children: [\n                  SizedBox(width: 5),\n                  Icon(Icons.add),\n                  SizedBox(width: 10),\n                  Text(\"Insert\", style: TextStyle(fontSize: 14)),\n                ],\n              ),\n            ),\n          if (keyPath != \"config\" && T == List)\n            const _PopupMenuWidget(\n              Row(\n                mainAxisSize: MainAxisSize.min,\n                children: [\n                  SizedBox(width: 5),\n                  Icon(Icons.add),\n                  SizedBox(width: 10),\n                  Text(\"Append\", style: TextStyle(fontSize: 14)),\n                ],\n              ),\n            ),\n          if (keyPath != \"config\" && (T == Map || T == List)) ...[\n            if ((keyPath == \"config.outbounds\" || keyPath == \"config.endpoints\") && T == List) ...[\n              for (final String key in protocolSchemaValues.keys) ...{\n                PopupMenuItem<_OptionItems>(\n                  height: _popupMenuHeight,\n                  padding: const EdgeInsets.only(left: _popupMenuItemPadding),\n                  value: key,\n                  child: Row(\n                    mainAxisSize: MainAxisSize.min,\n                    children: [\n                      const Icon(Icons.data_object),\n                      const SizedBox(width: 10),\n                      Text(key, style: const TextStyle(fontSize: 14)),\n                    ],\n                  ),\n                ),\n              },\n              const PopupMenuDivider(height: 1),\n            ],\n            if (T == Map) ...[\n              for (final String key in exampleSchemaValues.keys) ...{\n                if (keyPath == key)\n                  for (final String key2 in exampleSchemaValues[key]!.keys) ...{\n                    PopupMenuItem<_OptionItems>(\n                      height: _popupMenuHeight,\n                      padding: const EdgeInsets.only(left: _popupMenuItemPadding),\n                      value: key + \"___\" + key2,\n                      child: Row(\n                        mainAxisSize: MainAxisSize.min,\n                        children: [\n                          const Icon(Icons.data_object),\n                          const SizedBox(width: 10),\n                          Text(key2, style: const TextStyle(fontSize: 14)),\n                        ],\n                      ),\n                    ),\n                  },\n                const PopupMenuDivider(height: 1),\n              },\n            ],\n            if (keyPath != \"config\" &&\n                !(T == List && (keyPath == \"config.outbounds\" || keyPath == \"config.endpoints\"))) ...[\n              const PopupMenuItem<_OptionItems>(\n                height: _popupMenuHeight,\n                padding: EdgeInsets.only(left: _popupMenuItemPadding),\n                value: \"string\",\n                child: Row(\n                  mainAxisSize: MainAxisSize.min,\n                  children: [\n                    Icon(Icons.abc),\n                    SizedBox(width: 10),\n                    Text(\"String\", style: TextStyle(fontSize: 14)),\n                  ],\n                ),\n              ),\n              const PopupMenuItem<_OptionItems>(\n                height: _popupMenuHeight,\n                padding: EdgeInsets.only(left: _popupMenuItemPadding),\n                value: \"num\",\n                child: Row(\n                  mainAxisSize: MainAxisSize.min,\n                  children: [\n                    Icon(Icons.onetwothree),\n                    SizedBox(width: 10),\n                    Text(\"Number\", style: TextStyle(fontSize: 14)),\n                  ],\n                ),\n              ),\n              const PopupMenuItem<_OptionItems>(\n                height: _popupMenuHeight,\n                padding: EdgeInsets.only(left: _popupMenuItemPadding),\n                value: \"bool\",\n                child: Row(\n                  mainAxisSize: MainAxisSize.min,\n                  children: [\n                    Icon(Icons.check_rounded),\n                    SizedBox(width: 10),\n                    Text(\"Boolean\", style: TextStyle(fontSize: 14)),\n                  ],\n                ),\n              ),\n              const PopupMenuItem<_OptionItems>(\n                height: _popupMenuHeight,\n                padding: EdgeInsets.only(left: _popupMenuItemPadding),\n                value: \"map\",\n                child: Row(\n                  mainAxisSize: MainAxisSize.min,\n                  children: [\n                    Icon(Icons.data_object),\n                    SizedBox(width: 10),\n                    Text(\"object\", style: TextStyle(fontSize: 14)),\n                  ],\n                ),\n              ),\n              const PopupMenuItem<_OptionItems>(\n                height: _popupMenuHeight,\n                padding: EdgeInsets.only(left: _popupMenuItemPadding),\n                value: \"list\",\n                child: Row(\n                  mainAxisSize: MainAxisSize.min,\n                  children: [\n                    Icon(Icons.data_array),\n                    SizedBox(width: 10),\n                    Text(\"List\", style: TextStyle(fontSize: 14)),\n                  ],\n                ),\n              ),\n            ],\n          ],\n          const PopupMenuDivider(height: 1),\n          if (keyPath != \"config\" && !(T == List && (keyPath == \"config.outbounds\" || keyPath == \"config.endpoints\")))\n            const PopupMenuItem<_OptionItems>(\n              height: _popupMenuHeight,\n              padding: EdgeInsets.only(left: 5),\n              value: \"delete\",\n              child: Row(\n                mainAxisSize: MainAxisSize.min,\n                children: [\n                  Icon(Icons.delete),\n                  SizedBox(width: 10),\n                  Text(\"Delete\", style: TextStyle(fontSize: 14)),\n                ],\n              ),\n            ),\n        ];\n      },\n      child: _options,\n    );\n  }\n}\n\nclass _PopupMenuWidget extends PopupMenuEntry<Never> {\n  const _PopupMenuWidget(this.child);\n\n  final Widget child;\n\n  @override\n  final double height = _popupMenuHeight;\n\n  @override\n  bool represents(_) => false;\n\n  @override\n  State<_PopupMenuWidget> createState() => _PopupMenuWidgetState();\n}\n\nclass _PopupMenuWidgetState extends State<_PopupMenuWidget> {\n  @override\n  Widget build(BuildContext context) {\n    return widget.child;\n  }\n}\n\nclass _SearchField extends StatelessWidget {\n  final ValueChanged<String> onChanged;\n  final ValueChanged<_SearchActions> onAction;\n\n  const _SearchField(this.onChanged, this.onAction);\n\n  @override\n  Widget build(BuildContext context) {\n    return ColoredBox(\n      color: Theme.of(context).searchBarTheme.backgroundColor?.resolve({}) ?? Colors.black,\n      child: Row(\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          const SizedBox(width: 2),\n          const Icon(Icons.search, size: 20),\n          const SizedBox(width: 5),\n          TextField(\n            onChanged: onChanged,\n            autocorrect: false,\n            autofocus: true,\n            cursorWidth: 1,\n            // style: _textStyle,\n            cursorHeight: 12,\n            decoration: InputDecoration(\n              hintText: \"Search\",\n              hintStyle: Theme.of(context).textTheme.bodySmall,\n              constraints: const BoxConstraints(maxWidth: 100),\n              border: InputBorder.none,\n              // fillColor: Colors.transparent,\n              // filled: true,\n              isDense: true,\n              contentPadding: const EdgeInsets.all(3),\n              focusedBorder: InputBorder.none,\n              // hoverColor: Colors.transparent,\n            ),\n          ),\n          const SizedBox(width: 5),\n          InkWell(\n            onTap: () {\n              onAction(_SearchActions.next);\n            },\n            child: const Tooltip(message: 'Next', child: Icon(Icons.keyboard_arrow_down_rounded, size: 20)),\n          ),\n          const SizedBox(width: 2),\n          InkWell(\n            onTap: () {\n              onAction(_SearchActions.prev);\n            },\n            child: const Tooltip(message: 'Previous', child: Icon(Icons.keyboard_arrow_up_rounded, size: 20)),\n          ),\n          const SizedBox(width: 5),\n        ],\n      ),\n    );\n  }\n}\n\nList<String> _getSpace(int count) {\n  if (count == 0) return ['', '  '];\n\n  String space = '';\n  for (int i = 0; i < count; i++) {\n    space += '  ';\n  }\n  return [space, '$space  '];\n}\n\nString _stringifyData(data, int spacing, [bool isLast = false]) {\n  String str = '';\n  final spaceList = _getSpace(spacing);\n  final objectSpace = spaceList[0];\n  final dataSpace = spaceList[1];\n\n  if (data is Map) {\n    str += '$objectSpace{';\n    str += '\\n';\n    final keys = data.keys.toList();\n    for (int i = 0; i < keys.length; i++) {\n      str += '$dataSpace\"${keys[i]}\": ${_stringifyData(data[keys[i]], spacing + 1, i == keys.length - 1)}';\n      str += '\\n';\n    }\n    str += '$objectSpace}';\n    if (!isLast) str += ',';\n  } else if (data is List) {\n    str += '$objectSpace[';\n    str += '\\n';\n    for (int i = 0; i < data.length; i++) {\n      final item = data[i];\n      if (item is Map || item is List) {\n        str += _stringifyData(item, spacing + 1, i == data.length - 1);\n      } else {\n        str += '$dataSpace${_stringifyData(item, spacing + 1, i == data.length - 1)}';\n      }\n      str += '\\n';\n    }\n    str += '$objectSpace]';\n    if (!isLast) str += ',';\n  } else {\n    if (data is String) {\n      str = '\"$data\"';\n    } else {\n      str = '$data';\n    }\n    if (!isLast) str += ',';\n  }\n\n  return str;\n}\n"
  },
  {
    "path": "lib/features/profile/details/profile_details_notifier.dart",
    "content": "import 'dart:convert';\nimport 'dart:developer';\n\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/profile/data/profile_data_providers.dart';\nimport 'package:hiddify/features/profile/data/profile_repository.dart';\nimport 'package:hiddify/features/profile/details/profile_details_state.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/features/profile/model/profile_failure.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'profile_details_notifier.g.dart';\n\n@riverpod\nclass ProfileDetailsNotifier extends _$ProfileDetailsNotifier with AppLogger {\n  ProfileRepository get _profilesRepo => ref.read(profileRepositoryProvider).requireValue;\n\n  @override\n  Future<ProfileDetailsState> build(String id) async {\n    final prof = (await _profilesRepo.getById(id).run()).match((l) => throw l, (prof) {\n      // _originalProfile = prof;\n      if (prof == null) {\n        loggy.warning('profile with id: [$id] does not exist');\n        throw const ProfileNotFoundFailure();\n      }\n      return prof;\n    });\n    var profContent = \"\";\n    try {\n      profContent = (await _profilesRepo.generateConfig(id).run()).match(\n        (l) => throw Exception('Failed to generate config: $l'),\n        (content) => content,\n      );\n    } catch (e, st) {\n      loggy.error('Error generating config for profile $id', e, st);\n      // Optionally, you can set profContent to an empty string or keep the original content\n      profContent = await _profilesRepo.getRawConfig(id).run().then((e) => e.getOrElse((f) => \"\"));\n    }\n    try {\n      final jsonObject = jsonDecode(profContent);\n      final List<Map<String, dynamic>> outbounds = [];\n      if (jsonObject is Map<String, dynamic> && jsonObject['outbounds'] is List) {\n        for (final outbound in jsonObject['outbounds'] as List<dynamic>) {\n          if (outbound is Map<String, dynamic> &&\n              outbound['type'] != null &&\n              !['selector', 'urltest', 'dns', 'block'].contains(outbound['type']) &&\n              !['direct', 'bypass', 'direct-fragment'].contains(outbound['tag'])) {\n            outbounds.add(outbound);\n          }\n        }\n      } else {\n        // print('No outbounds found in the config');\n      }\n      final endpoints = jsonObject['endpoints'] as List? ?? [];\n      profContent = '{\"outbounds\": ${json.encode(outbounds)},\"endpoints\":${json.encode(endpoints)} }';\n      loggy.info(profContent);\n    } catch (e, st) {\n      loggy.error('Error parsing profile-content JSON', e, st);\n      // rethrow;\n    }\n    return ProfileDetailsState(\n      loadingState: const AsyncData(null),\n      profile: prof,\n      configContent: profContent,\n      isDetailsChanged: false,\n    );\n  }\n\n  Future<T?> doAsync<T>(Future<T> Function() operation) async {\n    if (state case AsyncData(value: final ProfileDetailsState data)) {\n      state = AsyncData(data.copyWith(loadingState: const AsyncLoading()));\n      final T? result = await operation();\n      state = AsyncData(data.copyWith(loadingState: const AsyncData(null)));\n      return result;\n    }\n    return null;\n  }\n\n  void setUserOverride(UserOverride userOverride) {\n    if (state case AsyncData(value: final ProfileDetailsState data)) {\n      state = AsyncData(\n        data.copyWith(profile: data.profile.copyWith(userOverride: userOverride), isDetailsChanged: true),\n      );\n    }\n  }\n\n  void setContent(String configContent) {\n    if (state case AsyncData(value: final ProfileDetailsState data)) {\n      state = AsyncData(data.copyWith(configContent: configContent, isDetailsChanged: true));\n    }\n  }\n\n  Future<bool> save() async {\n    bool success = false;\n    if (state case AsyncData(:final value)) {\n      if (value.loadingState case AsyncLoading()) return false;\n\n      success =\n          await doAsync<bool>(() async {\n            final t = await ref.read(translationsProvider.future);\n            return (await _profilesRepo.offlineUpdate(value.profile, value.configContent).run()).match(\n              (l) async {\n                await ref\n                    .read(dialogNotifierProvider.notifier)\n                    .showCustomAlertFromErr(\n                      t.presentError(l, action: t.pages.profiles.msg.update.failureNamed(name: value.profile.name)),\n                    );\n                return false;\n              },\n              (r) {\n                ref.read(inAppNotificationControllerProvider).showSuccessToast(t.pages.profiles.msg.update.success);\n                return true;\n              },\n            );\n          }) ??\n          false;\n    }\n    return success;\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/details/profile_details_page.dart",
    "content": "import 'dart:convert';\n\nimport 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/features/profile/details/json_editor.dart';\nimport 'package:hiddify/features/profile/details/profile_details_notifier.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ProfileDetailsPage extends HookConsumerWidget with PresLogger {\n  const ProfileDetailsPage({super.key, required this.id});\n\n  final String id;\n\n  String _genSliderText(Translations t, int sliderValue) {\n    if (sliderValue == 0) {\n      return t.common.auto;\n    } else if (sliderValue < 24) {\n      return t.common.interval.hour(n: sliderValue);\n    }\n    final day = t.common.interval.day(n: sliderValue ~/ 24);\n    final hour = t.common.interval.hour(n: sliderValue % 24);\n    return '$day $hour';\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final theme = Theme.of(context);\n    final t = ref.watch(translationsProvider).requireValue;\n    final formKey = useMemoized(() => GlobalKey<FormState>());\n    final provider = profileDetailsNotifierProvider(id);\n\n    return ref\n        .watch(ProfileDetailsNotifierProvider(id))\n        .when(\n          data: (data) {\n            final isLoading = data.loadingState is AsyncLoading;\n            final userOverride = data.profile.userOverride ?? const UserOverride();\n            final sliderFocusNode = useFocusNode(\n              onKeyEvent: (node, event) {\n                if (KeyboardConst.verticalArrows.contains(event.logicalKey) && event is KeyDownEvent) {\n                  if (event.logicalKey == LogicalKeyboardKey.arrowUp) {\n                    node.previousFocus();\n                  } else {\n                    node.nextFocus();\n                  }\n                  return KeyEventResult.handled;\n                }\n                return KeyEventResult.ignored;\n              },\n            );\n            return Scaffold(\n              appBar: AppBar(\n                title: Text(t.pages.profileDetails.title),\n                actions: [\n                  TextButton.icon(\n                    onPressed: isLoading || !data.isDetailsChanged\n                        ? null\n                        : () async {\n                            if (formKey.currentState!.validate()) {\n                              await ref.read(provider.notifier).save().then((success) {\n                                ref\n                                    .read(inAppNotificationControllerProvider)\n                                    .showSuccessToast(t.pages.profiles.msg.save.success);\n                                if (success && context.mounted) context.pop();\n                              });\n                            }\n                          },\n                    icon: const Icon(Icons.check),\n                    label: Text(t.common.save),\n                  ),\n                  const Gap(8),\n                ],\n              ),\n              body: ListView(\n                children: [\n                  Form(\n                    key: formKey,\n                    child: Column(\n                      children: [\n                        Padding(\n                          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),\n                          child: CustomTextFormField(\n                            maxLines: 1,\n                            initialValue: userOverride.name ?? data.profile.name,\n                            validator: (value) =>\n                                (value?.isEmpty ?? true) ? t.pages.profileDetails.form.emptyName : null,\n                            onChanged: (value) => ref\n                                .read(ProfileDetailsNotifierProvider(id).notifier)\n                                .setUserOverride(userOverride.copyWith(name: value)),\n                            label: t.common.name,\n                            hint: t.pages.profileDetails.form.nameHint,\n                          ),\n                        ),\n                        if (data.profile case RemoteProfileEntity(:final url))\n                          Padding(\n                            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),\n                            child: Column(\n                              crossAxisAlignment: CrossAxisAlignment.start,\n                              children: [\n                                Text(\n                                  t.common.url,\n                                  style: theme.textTheme.labelMedium!.copyWith(color: theme.colorScheme.onSurface),\n                                  maxLines: 1,\n                                  overflow: TextOverflow.ellipsis,\n                                ),\n                                const Gap(4),\n                                SelectableText(\n                                  url,\n                                  style: theme.textTheme.bodySmall!.copyWith(color: theme.colorScheme.onSurfaceVariant),\n                                ),\n                              ],\n                            ),\n                          ),\n                        const Divider(indent: 16, endIndent: 16),\n                        if (data.profile case RemoteProfileEntity(:final options)) ...[\n                          SwitchListTile.adaptive(\n                            title: Text(\n                              t.pages.profileDetails.form.disableAutoUpdate,\n                              style: theme.textTheme.titleSmall!.copyWith(color: theme.colorScheme.onSurface),\n                            ),\n                            value: userOverride.isAutoUpdateDisable,\n                            onChanged: (value) => ref\n                                .read(ProfileDetailsNotifierProvider(id).notifier)\n                                .setUserOverride(userOverride.copyWith(isAutoUpdateDisable: value)),\n                          ),\n                          AnimatedSize(\n                            alignment: Alignment.topCenter,\n                            duration: const Duration(milliseconds: 300),\n                            curve: Curves.easeInOut,\n                            child: !userOverride.isAutoUpdateDisable\n                                ? Column(\n                                    children: [\n                                      const Divider(indent: 16, endIndent: 16),\n                                      const Gap(12),\n                                      Padding(\n                                        padding: const EdgeInsets.symmetric(horizontal: 16),\n                                        child: Row(\n                                          children: [\n                                            Expanded(\n                                              child: Text(\n                                                t.pages.profileDetails.form.autoUpdateInterval,\n                                                style: theme.textTheme.titleSmall!.copyWith(\n                                                  color: theme.colorScheme.onSurface,\n                                                ),\n                                              ),\n                                            ),\n                                            Text(\n                                              _genSliderText(t, userOverride.updateInterval ?? 0),\n                                              style: theme.textTheme.labelSmall!.copyWith(\n                                                color: theme.colorScheme.onSurfaceVariant,\n                                              ),\n                                            ),\n                                          ],\n                                        ),\n                                      ),\n                                      const Gap(4),\n                                      Padding(\n                                        padding: const EdgeInsets.symmetric(horizontal: 10),\n                                        child: Slider(\n                                          focusNode: sliderFocusNode,\n                                          value:\n                                              userOverride.updateInterval?.toDouble() ??\n                                              options?.updateInterval.inHours.toDouble() ??\n                                              0.0,\n                                          max: 96,\n                                          divisions: 96,\n                                          label: (userOverride.updateInterval ?? 0).toString(),\n                                          onChanged: (double value) => ref\n                                              .read(ProfileDetailsNotifierProvider(id).notifier)\n                                              .setUserOverride(userOverride.copyWith(updateInterval: value.toInt())),\n                                        ),\n                                      ),\n                                    ],\n                                  )\n                                : const SizedBox.shrink(),\n                          ),\n                          const Divider(indent: 16, endIndent: 16),\n                        ],\n                        ListTile(\n                          title: Text(t.pages.profileDetails.lastUpdate),\n                          leading: const Icon(FluentIcons.history_24_regular),\n                          subtitle: Text(data.profile.lastUpdate.format()),\n                          dense: true,\n                        ),\n                        if (data.profile case RemoteProfileEntity(:final subInfo?)) ...[\n                          const Divider(indent: 16, endIndent: 16),\n                          Align(\n                            alignment: AlignmentDirectional.centerStart,\n                            child: Padding(\n                              padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 8),\n                              child: Column(\n                                crossAxisAlignment: CrossAxisAlignment.start,\n                                children: [\n                                  Text.rich(\n                                    style: Theme.of(context).textTheme.bodySmall,\n                                    TextSpan(\n                                      children: [\n                                        _buildSubProp(\n                                          FluentIcons.arrow_upload_16_regular,\n                                          subInfo.upload.size(),\n                                          t.components.subscriptionInfo.upload,\n                                        ),\n                                        const TextSpan(text: \"     \"),\n                                        _buildSubProp(\n                                          FluentIcons.arrow_download_16_regular,\n                                          subInfo.download.size(),\n                                          t.components.subscriptionInfo.download,\n                                        ),\n                                        const TextSpan(text: \"     \"),\n                                        _buildSubProp(\n                                          FluentIcons.arrow_bidirectional_up_down_16_regular,\n                                          subInfo.total.size(),\n                                          t.components.subscriptionInfo.total,\n                                        ),\n                                      ],\n                                    ),\n                                  ),\n                                  const Gap(12),\n                                  Text.rich(\n                                    style: Theme.of(context).textTheme.bodySmall,\n                                    TextSpan(\n                                      children: [\n                                        _buildSubProp(\n                                          FluentIcons.clock_dismiss_20_regular,\n                                          subInfo.expire.format(),\n                                          t.components.subscriptionInfo.expireDate,\n                                        ),\n                                      ],\n                                    ),\n                                  ),\n                                ],\n                              ),\n                            ),\n                          ),\n                        ],\n                        const Divider(),\n                      ],\n                    ),\n                  ),\n                  SizedBox(\n                    height: MediaQuery.of(context).size.height * 0.7,\n                    child: isJson(data.configContent)\n                        ? JsonEditor(\n                            expandedObjects: const [\"outbounds\", \"endpoints\"],\n                            onChanged: (value) {\n                              if (value == null) return;\n                              try {\n                                const encoder = JsonEncoder.withIndent('  ');\n                                ref.read(provider.notifier).setContent(encoder.convert(value));\n                              } catch (e) {\n                                ref.read(provider.notifier).setContent(\"$value\");\n                              }\n                            },\n                            enableHorizontalScroll: true,\n                            json: data.configContent,\n                          )\n                        : TextFormField(\n                            onChanged: (value) {\n                              ref.read(provider.notifier).setContent(value);\n                            },\n                            maxLines: null,\n                            minLines: null,\n                            expands: true,\n                            textAlignVertical: TextAlignVertical.top,\n                            decoration: const InputDecoration(\n                              border: InputBorder.none,\n                              contentPadding: EdgeInsets.only(left: 5, top: 8, bottom: 8),\n                            ),\n                          ),\n                  ),\n                ],\n              ),\n            );\n          },\n          error: (error, stackTrace) => Scaffold(\n            appBar: AppBar(title: Text(t.pages.profileDetails.title)),\n            body: Center(\n              child: Column(\n                mainAxisAlignment: MainAxisAlignment.center,\n                children: [\n                  const Icon(FluentIcons.error_circle_12_filled),\n                  Text(t.presentShortError(error)),\n                  Text(error.toString()),\n                ],\n              ),\n            ),\n          ),\n          loading: () => Scaffold(\n            appBar: AppBar(title: Text(t.pages.profileDetails.title)),\n            body: const Center(child: CircularProgressIndicator()),\n          ),\n        );\n  }\n\n  InlineSpan _buildSubProp(IconData icon, String text, String semanticLabel) {\n    return TextSpan(\n      children: [\n        WidgetSpan(child: Icon(icon, size: 16, semanticLabel: semanticLabel)),\n        const TextSpan(text: \" \"),\n        TextSpan(text: text),\n      ],\n    );\n  }\n}\n\nbool isJson(String value) {\n  try {\n    jsonDecode(value);\n    return true;\n  } catch (_) {\n    return false;\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/details/profile_details_state.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\npart 'profile_details_state.freezed.dart';\n\n@freezed\nclass ProfileDetailsState with _$ProfileDetailsState {\n  const ProfileDetailsState._();\n\n  const factory ProfileDetailsState({\n    required AsyncValue<void> loadingState,\n    required ProfileEntity profile,\n    required String configContent,\n    required bool isDetailsChanged,\n  }) = _ProfileDetailsState;\n\n  bool get isLoading => loadingState is AsyncLoading;\n}\n"
  },
  {
    "path": "lib/features/profile/model/profile_entity.dart",
    "content": "import 'dart:convert';\nimport 'dart:math';\n\nimport 'package:dartx/dartx.dart';\nimport 'package:freezed_annotation/freezed_annotation.dart';\n\npart 'profile_entity.freezed.dart';\npart 'profile_entity.g.dart';\n\nenum ProfileType { remote, local }\n\n@freezed\nsealed class ProfileEntity with _$ProfileEntity {\n  const ProfileEntity._();\n\n  const factory ProfileEntity.remote({\n    required String id,\n    required bool active,\n    required String name,\n    required String url,\n    required DateTime lastUpdate,\n    ProfileOptions? options,\n    SubscriptionInfo? subInfo,\n    Map<String, dynamic>? populatedHeaders,\n    String? profileOverride,\n    UserOverride? userOverride,\n  }) = RemoteProfileEntity;\n\n  const factory ProfileEntity.local({\n    required String id,\n    required bool active,\n    required String name,\n    required DateTime lastUpdate,\n    Map<String, dynamic>? populatedHeaders,\n    String? profileOverride,\n    UserOverride? userOverride,\n  }) = LocalProfileEntity;\n}\n\n@freezed\nclass ProfileOptions with _$ProfileOptions {\n  const factory ProfileOptions({@Default(Duration.zero) Duration updateInterval}) = _ProfileOptions;\n}\n\n@freezed\nclass SubscriptionInfo with _$SubscriptionInfo {\n  const SubscriptionInfo._();\n\n  const factory SubscriptionInfo({\n    required int upload,\n    required int download,\n    required int total,\n    required DateTime expire,\n    String? webPageUrl,\n    String? supportUrl,\n  }) = _SubscriptionInfo;\n\n  bool get isExpired => expire <= DateTime.now();\n\n  int get consumption => upload + download;\n  int get remainingBW => total - consumption;\n  double get remainingBWratio => (remainingBW / total).clamp(0, 1);\n  double get ratio => (consumption / total).clamp(0, 1);\n\n  Duration get remaining => expire.difference(DateTime.now());\n  double get remainingRatio => min(remaining.inDays, 30) / 30;\n}\n\nconst int latestUserOverrideVersion = 1;\n\n@freezed\nabstract class UserOverride with _$UserOverride {\n  const UserOverride._();\n\n  const factory UserOverride({\n    @Default(latestUserOverrideVersion) int version,\n    String? name,\n    @Default(false) bool isAutoUpdateDisable,\n    // hours\n    int? updateInterval,\n    bool? enableWarp,\n    bool? enableFragment,\n  }) = _UserOverride;\n\n  factory UserOverride.fromJson(Map<String, Object?> json) => _$UserOverrideFromJson(json);\n\n  String toStr() => jsonEncode(toJson());\n\n  static UserOverride? fromStr(String? str) {\n    if (str != null) {\n      final m = (jsonDecode(str) as Map).cast<String, Object?>();\n      return UserOverride.fromJson(_migrate(m));\n    }\n    return null;\n  }\n\n  static Map<String, dynamic> _migrate(Map<String, Object?> json) {\n    final version = json['version'] as int? ?? 1;\n\n    if (version < 2) {\n      // Migration 1 to 2\n    }\n    json['version'] = latestUserOverrideVersion;\n    return json;\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/model/profile_failure.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/features/settings/model/config_option_failure.dart';\n\npart 'profile_failure.freezed.dart';\n\n@freezed\nsealed class ProfileFailure with _$ProfileFailure, Failure {\n  const ProfileFailure._();\n\n  @With<UnexpectedFailure>()\n  const factory ProfileFailure.unexpected([Object? error, StackTrace? stackTrace]) = ProfileUnexpectedFailure;\n\n  const factory ProfileFailure.notFound() = ProfileNotFoundFailure;\n\n  @With<ExpectedFailure>()\n  const factory ProfileFailure.invalidUrl([String? message]) = ProfileInvalidUrlFailure;\n\n  @With<ExpectedFailure>()\n  const factory ProfileFailure.invalidConfig([String? message, ConfigOptionFailure? configOptionFailure]) =\n      ProfileInvalidConfigFailure;\n\n  @With<ExpectedFailure>()\n  const factory ProfileFailure.cancelByUser([String? message]) = ProfileCancelByUserFailure;\n\n  @override\n  ({String type, String? message}) present(TranslationsEn t) {\n    return switch (this) {\n      ProfileUnexpectedFailure() => (type: t.errors.profiles.unexpected, message: null),\n      ProfileNotFoundFailure() => (type: t.errors.profiles.notFound, message: null),\n      ProfileInvalidUrlFailure(:final message) => (type: t.errors.profiles.invalidUrl, message: message),\n      ProfileInvalidConfigFailure(:final message, :final configOptionFailure) =>\n        configOptionFailure?.present(t) ?? (type: t.errors.profiles.invalidConfig, message: message),\n      ProfileCancelByUserFailure(:final message) => (type: t.errors.profiles.canceledByUser, message: message),\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/model/profile_sort_enum.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\n\nenum ProfilesSort {\n  lastUpdate,\n  name;\n\n  String present(TranslationsEn t) {\n    return switch (this) {\n      lastUpdate => t.dialogs.sortProfiles.sort.name,\n      name => t.dialogs.sortProfiles.sort.lastUpdate,\n    };\n  }\n\n  IconData get icon => switch (this) {\n    lastUpdate => FluentIcons.history_24_regular,\n    name => FluentIcons.text_sort_ascending_24_regular,\n  };\n}\n\nenum SortMode { ascending, descending }\n"
  },
  {
    "path": "lib/features/profile/notifier/active_profile_notifier.dart",
    "content": "import 'package:hiddify/features/profile/data/profile_data_mapper.dart';\nimport 'package:hiddify/features/profile/data/profile_data_providers.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'active_profile_notifier.g.dart';\n\n@Riverpod(keepAlive: true)\nclass ActiveProfile extends _$ActiveProfile with AppLogger {\n  @override\n  Stream<ProfileEntity?> build() {\n    loggy.debug(\"watching active profile\");\n    return ref.watch(profileDataSourceProvider).watchActiveProfile().map((event) => event?.toEntity());\n  }\n}\n\n// TODO: move to specific feature\n@Riverpod(keepAlive: true)\nStream<bool> hasAnyProfile(Ref ref) {\n  return ref.watch(profileDataSourceProvider).watchProfilesCount().map((event) => event != 0).distinct();\n}\n"
  },
  {
    "path": "lib/features/profile/notifier/profile_notifier.dart",
    "content": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:dio/dio.dart';\nimport 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/haptic/haptic_service.dart';\nimport 'package:hiddify/core/http_client/http_client_provider.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/features/profile/add/model/free_profiles_model.dart';\nimport 'package:hiddify/features/profile/data/profile_data_providers.dart';\nimport 'package:hiddify/features/profile/data/profile_repository.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/features/profile/model/profile_failure.dart';\nimport 'package:hiddify/features/profile/notifier/active_profile_notifier.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/utils/riverpod_utils.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'profile_notifier.g.dart';\n\n@riverpod\nclass AddProfileNotifier extends _$AddProfileNotifier with AppLogger {\n  @override\n  AsyncValue<Unit?> build() {\n    ref.disposeDelay(const Duration(minutes: 1));\n    ref.onDispose(() {\n      loggy.debug(\"disposing\");\n      _cancelToken?.cancel();\n    });\n    listenSelf((previous, next) {\n      final t = ref.read(translationsProvider).requireValue;\n      final notification = ref.read(inAppNotificationControllerProvider);\n      switch (next) {\n        case AsyncData(value: final _?):\n          notification.showSuccessToast(t.pages.profiles.msg.save.success);\n        case AsyncError(:final error):\n          if (error case ProfileInvalidUrlFailure()) {\n            notification.showErrorToast(t.pages.profiles.msg.invalidUrl);\n          } else if (error case ProfileCancelByUserFailure()) {\n            return;\n          } else {\n            ref\n                .read(dialogNotifierProvider.notifier)\n                .showCustomAlertFromErr(t.presentError(error, action: t.pages.profiles.msg.add.failure));\n          }\n      }\n    });\n    ref.onDispose(() {\n      if (!(_cancelToken?.isCancelled ?? true)) _cancelToken?.cancel();\n    });\n    return const AsyncData(null);\n  }\n\n  ProfileRepository get _profilesRepo => ref.read(profileRepositoryProvider).requireValue;\n  CancelToken? _cancelToken;\n\n  Future<void> addClipboard(String rawInput) async {\n    if (state.isLoading) return;\n    state = const AsyncLoading();\n    state = await AsyncValue.guard(() async {\n      // final activeProfile = await ref.read(activeProfileProvider.future);\n      // final markAsActive = activeProfile == null || ref.read(Preferences.markNewProfileActive);\n      final TaskEither<ProfileFailure, Unit> task;\n      if (LinkParser.parse(rawInput) case (final rs)?) {\n        loggy.debug(\"adding profile, url: [${rs.url}]\");\n        task = _profilesRepo.upsertRemote(\n          rs.url,\n          userOverride: rs.name.isNotEmpty ? UserOverride(name: rs.name) : null,\n          cancelToken: _cancelToken = CancelToken(),\n        );\n      } else {\n        loggy.debug(\"adding profile, content\");\n        task = _profilesRepo.addLocal(safeDecodeBase64(rawInput));\n      }\n      return await task\n          .match(\n            (err) {\n              loggy.warning(\"failed to add profile\", err);\n              throw err;\n            },\n            (_) {\n              loggy.info(\"successfully added profile\");\n              return unit;\n            },\n          )\n          .run();\n    });\n  }\n\n  Future<void> addManual({required String url, required UserOverride userOverride}) async {\n    if (state.isLoading) return;\n    state = const AsyncLoading();\n    state = await AsyncValue.guard(() async {\n      final task = _profilesRepo.upsertRemote(url, userOverride: userOverride);\n      return await task\n          .match(\n            (err) {\n              loggy.warning(\"failed to add profile\", err);\n              throw err;\n            },\n            (r) {\n              loggy.info(\"successfully added profile, mark as active? [true]\");\n              return r;\n            },\n          )\n          .run();\n    });\n  }\n}\n\n@riverpod\nclass UpdateProfileNotifier extends _$UpdateProfileNotifier with AppLogger {\n  @override\n  AsyncValue<Unit?> build(String id) {\n    ref.disposeDelay(const Duration(minutes: 1));\n    listenSelf((previous, next) {\n      final t = ref.read(translationsProvider).requireValue;\n      final notification = ref.read(inAppNotificationControllerProvider);\n      switch (next) {\n        case AsyncData(value: final _?):\n          notification.showSuccessToast(t.pages.profiles.msg.update.success);\n        case AsyncError(:final error):\n          ref\n              .read(dialogNotifierProvider.notifier)\n              .showCustomAlertFromErr(t.presentError(error, action: t.pages.profiles.msg.update.failure));\n      }\n    });\n    return const AsyncData(null);\n  }\n\n  ProfileRepository get _profilesRepo => ref.read(profileRepositoryProvider).requireValue;\n\n  Future<void> updateProfile(RemoteProfileEntity profile) async {\n    if (state.isLoading) return;\n    state = const AsyncLoading();\n    await ref.read(hapticServiceProvider.notifier).lightImpact();\n    state = await AsyncValue.guard(() async {\n      return await _profilesRepo\n          .upsertRemote(profile.url)\n          .match(\n            (err) {\n              loggy.warning(\"failed to update profile\", err);\n              throw err;\n            },\n            (_) async {\n              loggy.info('successfully updated profile');\n\n              await ref.read(activeProfileProvider.future).then((active) async {\n                if (active != null && active.id == profile.id) {\n                  await ref.read(connectionNotifierProvider.notifier).reconnect(profile);\n                }\n              });\n              return unit;\n            },\n          )\n          .run();\n    });\n  }\n}\n\n@riverpod\nclass FreeSwitchNotifier extends _$FreeSwitchNotifier {\n  @override\n  bool build() {\n    return false;\n  }\n\n  Future<void> onChange(bool value) async => state = value;\n}\n\n@riverpod\nclass AddProfilePageNotifier extends _$AddProfilePageNotifier {\n  @override\n  AddProfilePages build() => AddProfilePages.options;\n\n  void goOptions() => state = AddProfilePages.options;\n  void goManual() => state = AddProfilePages.manual;\n}\n\nenum AddProfilePages { options, manual }\n\n@riverpod\nclass FreeProfilesNotifier extends _$FreeProfilesNotifier {\n  @override\n  Future<List<FreeProfile>> build() async {\n    final httpClient = ref.watch(httpClientProvider);\n    final res = await httpClient.get(\n      'https://raw.githubusercontent.com/hiddify/hiddify-app/refs/heads/main/test.configs/free_configs',\n    );\n    if (res.statusCode == 200) {\n      return FreeProfilesModel.fromJson(jsonDecode(res.data.toString()) as Map<String, dynamic>).profiles;\n    }\n    return <FreeProfile>[];\n  }\n}\n\n@riverpod\nFuture<List<FreeProfile>> freeProfilesFilteredByRegion(Ref ref) async {\n  final freeProfiles = await ref.watch(freeProfilesNotifierProvider.future);\n  final region = ref.watch(ConfigOptions.region);\n  return freeProfiles.where((e) => e.region.contains(region.name) || e.region.isEmpty).toList();\n}\n"
  },
  {
    "path": "lib/features/profile/notifier/profiles_update_notifier.dart",
    "content": "import 'package:dartx/dartx.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/features/profile/data/profile_data_providers.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:meta/meta.dart';\nimport 'package:neat_periodic_task/neat_periodic_task.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'profiles_update_notifier.g.dart';\n\ntypedef ProfileUpdateStatus = ({String name, bool success});\n\n@Riverpod(keepAlive: true)\nclass ForegroundProfilesUpdateNotifier extends _$ForegroundProfilesUpdateNotifier with AppLogger {\n  static const prefKey = \"profiles_update_check\";\n  static const interval = Duration(minutes: 15);\n\n  @override\n  Stream<ProfileUpdateStatus?> build() {\n    var cycleCount = 0;\n    _scheduler = NeatPeriodicTaskScheduler(\n      name: 'profiles update worker',\n      interval: interval,\n      timeout: const Duration(minutes: 5),\n      task: () async {\n        loggy.debug(\"cycle [${cycleCount++}]\");\n        await updateProfiles();\n      },\n    );\n\n    ref.onDispose(() async {\n      await _scheduler?.stop();\n      _scheduler = null;\n    });\n\n    if (ref.watch(Preferences.introCompleted)) {\n      loggy.debug(\"intro done, starting\");\n      _scheduler?.start();\n    } else {\n      loggy.debug(\"intro in process, skipping\");\n    }\n    return const Stream.empty();\n  }\n\n  NeatPeriodicTaskScheduler? _scheduler;\n  bool _forceNextRun = false;\n\n  Future<void> trigger() async {\n    loggy.debug(\"triggering update\");\n    _forceNextRun = true;\n    await _scheduler?.trigger();\n  }\n\n  @visibleForTesting\n  Future<void> updateProfiles() async {\n    var force = false;\n    if (_forceNextRun) {\n      force = true;\n      _forceNextRun = false;\n    }\n\n    try {\n      final previousRun = DateTime.tryParse(ref.read(sharedPreferencesProvider).requireValue.getString(prefKey) ?? \"\");\n\n      if (!force && previousRun != null && previousRun.add(interval) > DateTime.now()) {\n        loggy.debug(\"too soon! previous run: [$previousRun]\");\n        return;\n      }\n      loggy.debug(\"${force ? \"[FORCED] \" : \"\"}running, previous run: [$previousRun]\");\n\n      final remoteProfiles = await ref\n          .read(profileRepositoryProvider)\n          .requireValue\n          .watchAll()\n          .map(\n            (event) => event.getOrElse((f) {\n              loggy.error(\"error getting profiles\");\n              throw f;\n            }).whereType<RemoteProfileEntity>(),\n          )\n          .first;\n\n      await for (final profile in Stream.fromIterable(remoteProfiles)) {\n        final updateInterval = profile.options?.updateInterval;\n        if (force || updateInterval != null && updateInterval <= DateTime.now().difference(profile.lastUpdate)) {\n          final t = ref.read(translationsProvider).requireValue;\n          await ref\n              .read(profileRepositoryProvider)\n              .requireValue\n              .upsertRemote(profile.url)\n              .mapLeft((l) {\n                loggy.debug(\"error updating profile [${profile.id}]\", l);\n                ref\n                    .read(inAppNotificationControllerProvider)\n                    .showErrorToast(t.pages.profiles.msg.update.failureNamed(name: profile.name));\n                state = AsyncData((name: profile.name, success: false));\n              })\n              .map((_) {\n                loggy.debug(\"profile [${profile.id}] updated successfully\");\n                ref\n                    .read(inAppNotificationControllerProvider)\n                    .showSuccessToast(t.pages.profiles.msg.update.successNamed(name: profile.name));\n                state = AsyncData((name: profile.name, success: true));\n              })\n              .run();\n        } else {\n          loggy.debug(\n            \"skipping profile [${profile.id}] update. last successful update: [${profile.lastUpdate}] - interval: [${profile.options?.updateInterval}]\",\n          );\n        }\n      }\n    } finally {\n      await ref.read(sharedPreferencesProvider).requireValue.setString(prefKey, DateTime.now().toIso8601String());\n    }\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/overview/profiles_modal.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/profile/notifier/profiles_update_notifier.dart';\nimport 'package:hiddify/features/profile/overview/profiles_notifier.dart';\nimport 'package:hiddify/features/profile/widget/profile_tile.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ProfilesModal extends HookConsumerWidget {\n  const ProfilesModal({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final asyncProfiles = ref.watch(profilesNotifierProvider);\n\n    ref.listen(profilesNotifierProvider, (_, next) {\n      if (next.hasValue && next.value!.isEmpty) {\n        if (context.canPop()) context.pop();\n      }\n    });\n\n    final initialSize = PlatformUtils.isDesktop ? .60 : .35;\n    return SafeArea(\n      child: asyncProfiles.when(\n        data: (data) => DraggableScrollableSheet(\n          initialChildSize: initialSize,\n          maxChildSize: 0.85,\n          expand: false,\n          builder: (context, scrollController) => ScrollConfiguration(\n            behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),\n            child: Column(\n              children: [\n                Expanded(\n                  child: ListView.separated(\n                    padding: const EdgeInsets.all(12),\n                    separatorBuilder: (context, index) => const Gap(12),\n                    // shrinkWrap: true,\n                    controller: scrollController,\n                    itemBuilder: (context, index) => ProfileTile(profile: data[index]),\n                    itemCount: data.length,\n                  ),\n                ),\n                Padding(\n                  padding: const EdgeInsets.symmetric(horizontal: 16).copyWith(bottom: 8),\n                  child: Wrap(\n                    spacing: 8,\n                    runSpacing: 8,\n                    alignment: WrapAlignment.center,\n                    crossAxisAlignment: WrapCrossAlignment.center,\n                    children: [\n                      FilledButton.icon(\n                        label: Text(t.common.sort, maxLines: 1, overflow: TextOverflow.ellipsis),\n                        icon: const Icon(Icons.sort_rounded),\n                        onPressed: () => ref.read(dialogNotifierProvider.notifier).showSortProfiles(),\n                      ),\n                      FilledButton.icon(\n                        label: Text(t.pages.profiles.updateSubscriptions, maxLines: 1, overflow: TextOverflow.ellipsis),\n                        icon: const Icon(Icons.update_rounded),\n                        onPressed: () => ref.read(foregroundProfilesUpdateNotifierProvider.notifier).trigger(),\n                      ),\n                    ],\n                  ),\n                ),\n              ],\n            ),\n          ),\n        ),\n        loading: () => const Center(child: CircularProgressIndicator()),\n        error: (error, stackTrace) => Text(t.presentShortError(error)),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/overview/profiles_notifier.dart",
    "content": "import 'dart:async';\n\nimport 'package:flutter/services.dart';\nimport 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/haptic/haptic_service.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/features/profile/data/profile_data_providers.dart';\nimport 'package:hiddify/features/profile/data/profile_repository.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/features/profile/model/profile_sort_enum.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'profiles_notifier.g.dart';\n\n@riverpod\nclass ProfilesSortNotifier extends _$ProfilesSortNotifier with AppLogger {\n  @override\n  ({ProfilesSort by, SortMode mode}) build() {\n    return (by: ProfilesSort.lastUpdate, mode: SortMode.descending);\n  }\n\n  void changeSort(ProfilesSort sortBy) => state = (by: sortBy, mode: state.mode);\n\n  void toggleMode() =>\n      state = (by: state.by, mode: state.mode == SortMode.ascending ? SortMode.descending : SortMode.ascending);\n}\n\n@riverpod\nclass ProfilesNotifier extends _$ProfilesNotifier with AppLogger {\n  @override\n  Stream<List<ProfileEntity>> build() {\n    final sort = ref.watch(profilesSortNotifierProvider);\n    return _profilesRepo.watchAll(sort: sort.by, sortMode: sort.mode).map((event) => event.getOrElse((l) => throw l));\n  }\n\n  ProfileRepository get _profilesRepo => ref.read(profileRepositoryProvider).requireValue;\n\n  Future<Unit> selectActiveProfile(String id) async {\n    loggy.debug('changing active profile to: [$id]');\n    await ref.read(hapticServiceProvider.notifier).lightImpact();\n    return _profilesRepo.setAsActive(id).getOrElse((err) {\n      loggy.warning('failed to set [$id] as active profile', err);\n      throw err;\n    }).run();\n  }\n\n  Future<void> deleteProfile(ProfileEntity profile) async {\n    loggy.debug('deleting profile: ${profile.name}');\n\n    if (profile.active) await ref.read(connectionNotifierProvider.notifier).abortConnection();\n    await _profilesRepo\n        .deleteById(profile.id, profile.active)\n        .match(\n          (err) {\n            loggy.warning('failed to delete profile', err);\n            throw err;\n          },\n          (_) {\n            loggy.info('successfully deleted profile, was active? [${profile.active}]');\n            final t = ref.read(translationsProvider).requireValue;\n            ref.read(inAppNotificationControllerProvider).showSuccessToast(t.pages.profiles.msg.delete.success);\n            return unit;\n          },\n        )\n        .run();\n  }\n\n  Future<void> exportConfigToClipboard(ProfileEntity profile) async {\n    await _profilesRepo\n        .generateConfig(profile.id)\n        .match(\n          (err) {\n            loggy.warning('error generating config', err);\n            throw err;\n          },\n          (configJson) async {\n            await Clipboard.setData(ClipboardData(text: configJson));\n            final t = ref.read(translationsProvider).requireValue;\n            ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.export.clipboard.success);\n          },\n        )\n        .run();\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/overview/profiles_page.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/core/router/bottom_sheets/bottom_sheets_notifier.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/profile/notifier/profiles_update_notifier.dart';\nimport 'package:hiddify/features/profile/overview/profiles_notifier.dart';\nimport 'package:hiddify/features/profile/widget/profile_tile.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ProfilesPage extends HookConsumerWidget {\n  const ProfilesPage({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final asyncProfiles = ref.watch(profilesNotifierProvider);\n\n    ref.listen(profilesNotifierProvider, (_, next) {\n      if (next.hasValue && next.value!.isEmpty) {\n        context.goNamed('home');\n      }\n    });\n\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(t.pages.profiles.title),\n        actions: [\n          IconButton(\n            onPressed: () => ref.read(foregroundProfilesUpdateNotifierProvider.notifier).trigger(),\n            icon: const Icon(Icons.update_rounded),\n            tooltip: t.pages.profiles.updateSubscriptions,\n          ),\n          IconButton(\n            onPressed: () => ref.read(dialogNotifierProvider.notifier).showSortProfiles(),\n            icon: const Icon(Icons.sort_rounded),\n            tooltip: t.common.sort,\n          ),\n          const Gap(8),\n        ],\n      ),\n      floatingActionButton: FloatingActionButton.extended(\n        onPressed: () async => await ref.read(bottomSheetsNotifierProvider.notifier).showAddProfile(),\n        label: Text(t.pages.profiles.add),\n        icon: const Icon(Icons.add_rounded),\n      ),\n      body: asyncProfiles.when(\n        data: (data) => ListView.separated(\n          padding: const EdgeInsets.all(12).copyWith(bottom: 84),\n          separatorBuilder: (context, index) => const Gap(12),\n          itemBuilder: (context, index) => ProfileTile(profile: data[index]),\n          itemCount: data.length,\n        ),\n        loading: () => const Center(child: CircularProgressIndicator()),\n        error: (error, stackTrace) => Text(t.presentShortError(error)),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/widget/profile_tile.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/rendering.dart';\nimport 'package:flutter/services.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/router/bottom_sheets/bottom_sheets_notifier.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/core/router/go_router/helper/active_breakpoint_notifier.dart';\nimport 'package:hiddify/core/widget/adaptive_icon.dart';\nimport 'package:hiddify/core/widget/adaptive_menu.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/features/profile/notifier/profile_notifier.dart';\nimport 'package:hiddify/features/profile/overview/profiles_notifier.dart';\nimport 'package:hiddify/gen/fonts.gen.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nimport 'package:url_launcher/url_launcher.dart';\n\nclass ProfileTile extends HookConsumerWidget {\n  const ProfileTile({super.key, required this.profile, this.isMain = false, this.margin = EdgeInsets.zero, this.color});\n\n  final ProfileEntity profile;\n\n  /// home screen active profile card\n  final bool isMain;\n  final EdgeInsets margin;\n  final Color? color;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final theme = Theme.of(context);\n\n    final selectActiveMutation = useMutation(\n      initialOnFailure: (err) {\n        CustomToast.error(t.presentShortError(err)).show(context);\n      },\n      initialOnSuccess: () {\n        if (context.mounted && context.canPop()) context.pop();\n      },\n    );\n\n    final subInfo = switch (profile) {\n      RemoteProfileEntity(:final subInfo) => subInfo,\n      _ => null,\n    };\n\n    final showActionButton = profile is RemoteProfileEntity || !isMain;\n\n    // final effectiveMargin = isMain ? const EdgeInsets.symmetric(horizontal: 16, vertical: 8) : const EdgeInsets.only(left: 12, right: 12, bottom: 12);\n    // final double effectiveElevation = profile.active ? 12 : 4;\n    // final effectiveOutlineColor = profile.active ? theme.colorScheme.outline : Colors.transparent;\n    return Card(\n      // margin: effectiveMargin,\n      // elevation: effectiveElevation,\n      margin: margin,\n      shape: RoundedRectangleBorder(\n        side: profile.active ? BorderSide(color: theme.colorScheme.outline) : BorderSide.none,\n        borderRadius: ProfileTileConst.cardBorderRadius,\n      ),\n      // color: color ?? theme.colorScheme.secondaryContainer,\n      elevation: profile.active ? 0 : 1,\n\n      // shadowColor: Colors.transparent,\n      child: IntrinsicHeight(\n        child: ConstrainedBox(\n          constraints: const BoxConstraints(minHeight: 48),\n          child: Row(\n            crossAxisAlignment: CrossAxisAlignment.stretch,\n            children: [\n              if (showActionButton) ...[\n                SizedBox(\n                  width: 48,\n                  child: Semantics(sortKey: const OrdinalSortKey(1), child: ProfileActionButton(profile, !isMain)),\n                ),\n                if (profile.active) VerticalDivider(width: 1, color: theme.colorScheme.outline) else const Gap(1),\n              ],\n              Expanded(\n                child: Semantics(\n                  button: true,\n                  sortKey: isMain ? const OrdinalSortKey(0) : null,\n                  focused: isMain,\n                  liveRegion: isMain,\n                  namesRoute: isMain,\n                  label: isMain ? t.pages.profiles.viewAllProfiles : null,\n                  child: InkWell(\n                    borderRadius: showActionButton\n                        ? ProfileTileConst.endBorderRadius(Directionality.of(context))\n                        : ProfileTileConst.cardBorderRadius,\n                    onTap: () {\n                      if (isMain) {\n                        if (Breakpoint(context).isMobile()) {\n                          ref.read(bottomSheetsNotifierProvider.notifier).showProfilesOverview();\n                        } else {\n                          context.goNamed('profiles');\n                        }\n                      } else {\n                        if (selectActiveMutation.state.isInProgress) return;\n                        // if (profile.active) return;\n                        selectActiveMutation.setFuture(\n                          ref.read(profilesNotifierProvider.notifier).selectActiveProfile(profile.id),\n                        );\n                        if (context.canPop()) {\n                          context.pop();\n                        } else {\n                          context.goNamed('home');\n                        }\n                      }\n                    },\n                    child: Padding(\n                      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),\n                      child: Column(\n                        // mainAxisSize: MainAxisSize.min,\n                        mainAxisAlignment: MainAxisAlignment.center,\n                        crossAxisAlignment: CrossAxisAlignment.start,\n                        children: [\n                          if (isMain)\n                            Padding(\n                              padding: const EdgeInsets.symmetric(vertical: 4),\n                              child: Material(\n                                borderRadius: BorderRadius.circular(8),\n                                color: Colors.transparent,\n                                clipBehavior: Clip.antiAlias,\n                                child: Row(\n                                  mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                                  children: [\n                                    Flexible(\n                                      child: Text(\n                                        profile.name,\n                                        maxLines: 2,\n                                        overflow: TextOverflow.ellipsis,\n                                        style: theme.textTheme.titleMedium?.copyWith(\n                                          fontFamily: PlatformUtils.isWindows ? FontFamily.emoji : null,\n                                        ),\n                                        semanticsLabel: t.pages.profiles.activeProfileName(name: profile.name),\n                                      ),\n                                    ),\n                                    const Icon(Icons.arrow_drop_down_rounded),\n                                  ],\n                                ),\n                              ),\n                            )\n                          else\n                            Text(\n                              profile.name,\n                              maxLines: 2,\n                              overflow: TextOverflow.ellipsis,\n                              style: theme.textTheme.titleMedium?.copyWith(\n                                fontFamily: PlatformUtils.isWindows ? FontFamily.emoji : null,\n                              ),\n                              semanticsLabel: profile.active\n                                  ? t.pages.profiles.activeProfileName(name: profile.name)\n                                  : t.pages.profiles.nonActiveProfileName(name: profile.name),\n                            ),\n                          if (subInfo != null) ...[\n                            const Gap(4),\n                            RemainingTrafficIndicator(subInfo.ratio),\n                            const Gap(4),\n                            ProfileSubscriptionInfo(subInfo),\n                            const Gap(4),\n                          ],\n                        ],\n                      ),\n                    ),\n                  ),\n                ),\n              ),\n            ],\n          ),\n        ),\n      ),\n    );\n  }\n}\n\nclass ProfileActionButton extends HookConsumerWidget {\n  const ProfileActionButton(this.profile, this.showAllActions, {super.key});\n\n  final ProfileEntity profile;\n  final bool showAllActions;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    if (profile case RemoteProfileEntity() when !showAllActions) {\n      return Semantics(\n        button: true,\n        enabled: !ref.watch(updateProfileNotifierProvider(profile.id)).isLoading,\n        child: Tooltip(\n          message: t.pages.profiles.update,\n          child: InkWell(\n            borderRadius: ProfileTileConst.startBorderRadius(Directionality.of(context)),\n            onTap: () {\n              if (ref.read(updateProfileNotifierProvider(profile.id)).isLoading) {\n                return;\n              }\n              ref\n                  .read(updateProfileNotifierProvider(profile.id).notifier)\n                  .updateProfile(profile as RemoteProfileEntity);\n            },\n            child: const Icon(Icons.update_rounded),\n          ),\n        ),\n      );\n    }\n    return ProfileActionsMenu(profile, (context, toggleVisibility, _) {\n      return Semantics(\n        button: true,\n        child: Tooltip(\n          message: MaterialLocalizations.of(context).showMenuTooltip,\n          child: InkWell(\n            borderRadius: ProfileTileConst.startBorderRadius(Directionality.of(context)),\n            onTap: toggleVisibility,\n            child: Icon(AdaptiveIcon(context).more),\n          ),\n        ),\n      );\n    });\n  }\n}\n\nclass ProfileActionsMenu extends HookConsumerWidget {\n  const ProfileActionsMenu(this.profile, this.builder, {super.key, this.child});\n\n  final ProfileEntity profile;\n  final AdaptiveMenuBuilder builder;\n  final Widget? child;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    final menuItems = [\n      if (profile case RemoteProfileEntity())\n        AdaptiveMenuItem(\n          title: t.common.update,\n          icon: Icons.update_rounded,\n          onTap: () {\n            if (ref.read(updateProfileNotifierProvider(profile.id)).isLoading) {\n              return;\n            }\n            ref.read(updateProfileNotifierProvider(profile.id).notifier).updateProfile(profile as RemoteProfileEntity);\n          },\n        ),\n      AdaptiveMenuItem(\n        title: t.common.share,\n        icon: AdaptiveIcon(context).share,\n        subItems: [\n          if (profile case RemoteProfileEntity(:final url, :final name)) ...[\n            AdaptiveMenuItem(\n              title: t.pages.profiles.share.urlToClipboard,\n              onTap: () async {\n                final link = LinkParser.generateSubShareLink(url, name);\n                if (link.isNotEmpty) {\n                  await Clipboard.setData(ClipboardData(text: link));\n                  if (context.mounted) {\n                    ref\n                        .read(inAppNotificationControllerProvider)\n                        .showSuccessToast(t.common.msg.export.clipboard.success);\n                  }\n                }\n              },\n            ),\n            AdaptiveMenuItem(\n              title: t.pages.profiles.share.showUrlQr,\n              onTap: () async {\n                final link = LinkParser.generateSubShareLink(url, name);\n                if (link.isNotEmpty) {\n                  await ref.read(dialogNotifierProvider.notifier).showQrCode(link, message: name);\n                }\n              },\n            ),\n          ],\n          AdaptiveMenuItem(\n            title: t.pages.profiles.share.jsonToClipboard,\n            onTap: () async => await ref.read(profilesNotifierProvider.notifier).exportConfigToClipboard(profile),\n          ),\n        ],\n      ),\n      AdaptiveMenuItem(\n        icon: Icons.edit_rounded,\n        title: t.common.edit,\n        onTap: () {\n          if (Breakpoint(context).isMobile()) context.pop();\n          context.goNamed('profileDetails', pathParameters: {'id': profile.id});\n        },\n      ),\n      // if (!profile.active)\n      AdaptiveMenuItem(\n        icon: Icons.delete_outline_rounded,\n        title: t.common.delete,\n        onTap: () async => await ref\n            .read(dialogNotifierProvider.notifier)\n            .showConfirmation(\n              title: t.dialogs.confirmation.profile.delete.title,\n              message: t.dialogs.confirmation.profile.delete.msg,\n            )\n            .then((deleteConfirmed) async {\n              if (!deleteConfirmed) return;\n              await ref.read(profilesNotifierProvider.notifier).deleteProfile(profile);\n            }),\n      ),\n    ];\n\n    return AdaptiveMenu(builder: builder, items: menuItems, child: child);\n  }\n}\n\n// TODO add support url\nclass ProfileSubscriptionInfo extends HookConsumerWidget {\n  const ProfileSubscriptionInfo(this.subInfo, {super.key});\n\n  final SubscriptionInfo subInfo;\n\n  (String, Color?) remainingText(TranslationsEn t, ThemeData theme) {\n    if (subInfo.isExpired) {\n      return (t.components.subscriptionInfo.expired, theme.colorScheme.error);\n    } else if (subInfo.ratio >= 1) {\n      return (t.components.subscriptionInfo.noTraffic, theme.colorScheme.error);\n    } else if (subInfo.remaining.inDays > 365) {\n      return (t.components.subscriptionInfo.remainingDuration(duration: \"∞\"), null);\n    } else {\n      return (t.components.subscriptionInfo.remainingDuration(duration: subInfo.remaining.inDays), null);\n    }\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final theme = Theme.of(context);\n\n    final remaining = remainingText(t, theme);\n    return Row(\n      mainAxisAlignment: MainAxisAlignment.spaceBetween,\n      children: [\n        Directionality(\n          textDirection: TextDirection.ltr,\n          child: Flexible(\n            child: Text(\n              subInfo.total >\n                      10 *\n                          1099511627776 //10TB\n                  ? \"∞ GiB\"\n                  : subInfo.consumption.sizeOf(subInfo.total),\n              semanticsLabel: t.components.subscriptionInfo.remainingTrafficSemanticLabel(\n                consumed: subInfo.consumption.sizeGB(),\n                total: subInfo.total.sizeGB(),\n              ),\n              style: theme.textTheme.bodySmall,\n              overflow: TextOverflow.ellipsis,\n            ),\n          ),\n        ),\n        Flexible(\n          child: Text(\n            remaining.$1,\n            style: theme.textTheme.bodySmall?.copyWith(color: remaining.$2),\n            overflow: TextOverflow.ellipsis,\n          ),\n        ),\n      ],\n    );\n  }\n}\n\n// TODO add support url\nclass NewTrafficSubscriptionInfo extends HookConsumerWidget {\n  const NewTrafficSubscriptionInfo(this.subInfo, {super.key});\n\n  final SubscriptionInfo subInfo;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    return Column(\n      children: [\n        const Icon(Icons.assessment_rounded, color: Colors.blue),\n        Text(t.components.subscriptionInfo.remainingTraffic),\n        const SizedBox(height: 4),\n        Row(\n          mainAxisAlignment: MainAxisAlignment.center,\n          mainAxisSize: MainAxisSize.min,\n          children: [\n            Directionality(\n              textDirection: TextDirection.ltr,\n              child: Text(\n                subInfo.total >\n                        10 *\n                            1099511627776 //10TB\n                    ? \"∞ GiB\"\n                    : subInfo.consumption.sizeOf(subInfo.total),\n                semanticsLabel: t.components.subscriptionInfo.remainingTrafficSemanticLabel(\n                  consumed: subInfo.consumption.sizeGB(),\n                  total: subInfo.total.sizeGB(),\n                ),\n                // style: theme.textTheme.body,\n                overflow: TextOverflow.ellipsis,\n              ),\n            ),\n          ],\n        ),\n      ],\n    );\n  }\n}\n\n// TODO add support url\nclass NewDaySubscriptionInfo extends HookConsumerWidget {\n  const NewDaySubscriptionInfo(this.subInfo, {super.key});\n\n  final SubscriptionInfo subInfo;\n\n  (String, Color?) remainingText(TranslationsEn t, ThemeData theme) {\n    if (subInfo.isExpired) {\n      return (t.components.subscriptionInfo.expired, theme.colorScheme.error);\n    } else if (subInfo.ratio >= 1) {\n      return (t.components.subscriptionInfo.noTraffic, theme.colorScheme.error);\n    } else if (subInfo.remaining.inDays > 365) {\n      return (t.components.subscriptionInfo.remainingDurationNew(duration: \"∞\"), null);\n    } else {\n      return (t.components.subscriptionInfo.remainingDurationNew(duration: subInfo.remaining.inDays), null);\n    }\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final theme = Theme.of(context);\n\n    final remaining = remainingText(t, theme);\n    return Column(\n      children: [\n        const Icon(Icons.timer, color: Colors.blue),\n        Text(t.components.subscriptionInfo.remainingTime),\n        const SizedBox(height: 4),\n        Row(\n          mainAxisAlignment: MainAxisAlignment.center,\n          mainAxisSize: MainAxisSize.min,\n          children: [\n            Flexible(\n              child: Text(\n                remaining.$1,\n                // style: theme.textTheme.bodySmall?.copyWith(color: remaining.$2),\n                overflow: TextOverflow.ellipsis,\n              ),\n            ),\n          ],\n        ),\n      ],\n    );\n  }\n}\n\n// TODO add support url\nclass NewDayTrafficSubscriptionInfo extends HookConsumerWidget {\n  const NewDayTrafficSubscriptionInfo(this.subInfo, {super.key});\n\n  final SubscriptionInfo subInfo;\n\n  (String, Color?) remainingText(TranslationsEn t, ThemeData theme) {\n    if (subInfo.isExpired) {\n      return (t.components.subscriptionInfo.expired, theme.colorScheme.error);\n    } else if (subInfo.ratio >= 1) {\n      return (t.components.subscriptionInfo.noTraffic, theme.colorScheme.error);\n    } else if (subInfo.remaining.inDays > 365) {\n      return (t.components.subscriptionInfo.remainingDurationNew(duration: \"∞\"), null);\n    } else {\n      return (t.components.subscriptionInfo.remainingDurationNew(duration: subInfo.remaining.inDays), null);\n    }\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final theme = Theme.of(context);\n\n    final remaining = remainingText(t, theme);\n    return Column(\n      mainAxisAlignment: MainAxisAlignment.center,\n      children: [\n        const Icon(Icons.assessment_rounded, color: Colors.blue),\n        Text(t.components.subscriptionInfo.remainingUsage),\n        const SizedBox(height: 4),\n        Text(\n          remaining.$1,\n          // style: theme.textTheme.bodySmall?.copyWith(color: remaining.$2),\n          overflow: TextOverflow.ellipsis,\n        ),\n        Directionality(\n          textDirection: TextDirection.ltr,\n          child: Text(\n            subInfo.total >\n                    10 *\n                        1099511627776 //10TB\n                ? \"∞ GiB\"\n                : subInfo.consumption.sizeOf(subInfo.total),\n            semanticsLabel: t.components.subscriptionInfo.remainingTrafficSemanticLabel(\n              consumed: subInfo.consumption.sizeGB(),\n              total: subInfo.total.sizeGB(),\n            ),\n            // style: theme.textTheme.body,\n            overflow: TextOverflow.ellipsis,\n          ),\n        ),\n      ],\n    );\n  }\n}\n\nclass NewSiteSubscriptionInfo extends HookConsumerWidget {\n  const NewSiteSubscriptionInfo(this.subInfo, {super.key});\n\n  final SubscriptionInfo subInfo;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final uri = Uri.parse(subInfo.webPageUrl ?? \"\");\n    var host = uri.host;\n    if ([\"telegram.me\", \"t.me\"].contains(host)) {\n      host = \"@${uri.path.split(\"/\").last}\";\n    }\n    return InkWell(\n      onTap: () => launchUrl(Uri.parse(subInfo.webPageUrl ?? \"\")),\n      child: Column(\n        children: [\n          const Icon(FluentIcons.globe_person_24_filled, size: 24, color: Colors.blue),\n          Text(t.components.subscriptionInfo.profileSite),\n          const SizedBox(height: 4),\n          Row(\n            mainAxisAlignment: MainAxisAlignment.center,\n            mainAxisSize: MainAxisSize.min,\n            children: [\n              Flexible(\n                child: Text(\n                  host,\n                  // style: theme.textTheme.bodySmall?.copyWith(color: remaining.$2),\n                  overflow: TextOverflow.ellipsis,\n                ),\n              ),\n            ],\n          ),\n        ],\n      ),\n    );\n  }\n}\n\n// TODO change colors\nclass RemainingTrafficIndicator extends StatelessWidget {\n  const RemainingTrafficIndicator(this.ratio, {super.key});\n\n  final double ratio;\n\n  @override\n  Widget build(BuildContext context) {\n    // final startColor = ratio < 0.25\n    //     ? const Color.fromRGBO(93, 205, 251, 1.0)\n    //     : ratio < 0.65\n    //         ? const Color.fromRGBO(205, 199, 64, 1.0)\n    //         : const Color.fromRGBO(241, 82, 81, 1.0);\n    // final endColor = ratio < 0.25\n    //     ? const Color.fromRGBO(49, 146, 248, 1.0)\n    //     : ratio < 0.65\n    //         ? const Color.fromRGBO(98, 115, 32, 1.0)\n    //         : const Color.fromRGBO(139, 30, 36, 1.0);\n    return LinearProgressIndicator(value: ratio, borderRadius: BorderRadius.circular(16), minHeight: 6);\n    // return HorizontalPercentIndicator(\n    //   height: 6,\n\n    //   borderRadius: 16,\n    //   loadingPercent: ratio,\n    //   // inactiveTrackColor: Color.fromRGBO(r, g, b, opacity),\n\n    //   activeTrackColor: [startColor, endColor],\n    // );\n    // return LinearPercentIndicator(\n    //     // percent: ratio,\n    //     // animation: false,\n    //     // padding: EdgeInsets.zero,\n    //     // lineHeight: 6,\n    //     // barRadius: const Radius.circular(16),\n    //     // linearGradient: LinearGradient(\n    //     //   colors: [startColor, endColor],\n    //     // ),\n    //     );\n  }\n}\n"
  },
  {
    "path": "lib/features/profile/widget/profile_tile_main.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:hiddify/features/profile/notifier/profile_notifier.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:url_launcher/url_launcher.dart';\n\nclass ProfileTileMain extends HookConsumerWidget {\n  const ProfileTileMain({super.key, required this.profile, this.isMain = false});\n\n  final ProfileEntity profile;\n  final bool isMain;\n  static const verifiedDomains = [\n    'hiddify.com',\n    // 't.me',\n    // 'telegram.me',\n    // 'instagram.com',\n    // 'x.com',\n    // 'facebook.com',\n  ];\n  static const verifiedLinks = [\n    'https://t.me/hiddify',\n    'https://t.me/hiddify_board',\n    'https://instagram.com/hiddify_com',\n    'https://x.com/hiddify_com',\n    'https://facebook.com/hiddify',\n  ];\n  Future<void> _launchUrlWithCheck(BuildContext context, WidgetRef ref, String url) async {\n    final uri = Uri.parse(url);\n    final host = uri.host.toLowerCase();\n\n    if (verifiedDomains.any((p) => host == p || host.endsWith(\".$p\")) || verifiedLinks.any((p) => url == p)) {\n      await launchUrl(uri);\n      return;\n    }\n\n    // Show warning dialog for unknown domains\n    final shouldLaunch = await ref.read(dialogNotifierProvider.notifier).showUnknownDomainsWarning(url: url);\n    if (shouldLaunch == true) {\n      await launchUrl(uri);\n    }\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final theme = Theme.of(context);\n\n    final subInfo = switch (profile) {\n      RemoteProfileEntity(:final subInfo) => subInfo,\n      _ => null,\n    };\n\n    if (!isMain) return const Card();\n\n    return Material(\n      color: Colors.transparent,\n      child: Column(\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          Padding(\n            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),\n            child: InkWell(\n              onTap: () => ref\n                  .read(updateProfileNotifierProvider(profile.id).notifier)\n                  .updateProfile(profile as RemoteProfileEntity),\n              borderRadius: BorderRadius.circular(12),\n              child: Row(\n                mainAxisSize: MainAxisSize.min,\n                children: [\n                  Container(\n                    padding: const EdgeInsets.all(8),\n                    decoration: BoxDecoration(\n                      color: theme.colorScheme.primaryContainer.withOpacity(0.1),\n                      borderRadius: BorderRadius.circular(8),\n                    ),\n                    child: Icon(FluentIcons.arrow_sync_24_filled, color: theme.colorScheme.primary, size: 20),\n                  ),\n                  const Gap(6),\n                  Text(\n                    profile.name,\n                    style: theme.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600),\n                    maxLines: 1,\n                    overflow: TextOverflow.ellipsis,\n                  ),\n                ],\n              ),\n            ),\n          ),\n          if (subInfo != null)\n            Container(\n              width: 350,\n              child: Column(\n                mainAxisSize: MainAxisSize.min,\n                children: [\n                  IntrinsicHeight(\n                    // Add this to ensure equal height\n                    child: Row(\n                      children: [\n                        if (subInfo.total > 0) _BandwithUsageRow(subInfo),\n\n                        // if (subInfo.total > 0 && subInfo.remaining.inDays > 0)\n                        //   const VerticalDivider(\n                        //     // Add divider between items\n                        //     width: 1,\n                        //     thickness: 1,\n                        //     indent: 12,\n                        //     endIndent: 12,\n                        //   ),\n                        if (subInfo.remaining.inDays > 0)\n                          // Add Expanded\n                          _UsageRow(\n                            icon: null, //FluentIcons.timer_24_regular,\n                            title: subInfo.remaining.inDays > 365\n                                ? \"∞ days remaining\"\n                                : \"${subInfo.remaining.inDays}/30 days remaining\",\n                            progress: subInfo.remaining.inDays > 365 ? 0 : subInfo.remaining.inDays / 30,\n                            color: _getProgressColor(1 - (subInfo.remaining.inDays / 30)),\n                          ),\n                      ],\n                    ),\n                  ),\n                  if ((subInfo.webPageUrl != null || subInfo.supportUrl != null))\n                    Padding(\n                      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),\n                      child: Row(\n                        children: [\n                          if (subInfo.webPageUrl != null)\n                            Expanded(\n                              child: InkWell(\n                                onTap: () => _launchUrlWithCheck(context, ref, subInfo.webPageUrl!),\n                                borderRadius: BorderRadius.circular(8),\n                                child: _InfoItem(\n                                  icon: _getLinkIcon(subInfo.webPageUrl!, FluentIcons.building_shop_24_regular),\n                                  label: t.components.subscriptionInfo.profileSite,\n                                  value: _formatSupportLink(subInfo.webPageUrl!),\n                                ),\n                              ),\n                            ),\n                          if (subInfo.supportUrl != null) ...[\n                            const Gap(12),\n                            Expanded(\n                              child: InkWell(\n                                onTap: () => _launchUrlWithCheck(context, ref, subInfo.supportUrl!),\n                                borderRadius: BorderRadius.circular(8),\n                                child: _InfoItem(\n                                  icon: _getLinkIcon(subInfo.supportUrl!, FontAwesomeIcons.headset),\n                                  label: t.components.subscriptionInfo.profileSupport,\n                                  value: _formatSupportLink(subInfo.supportUrl!),\n                                ),\n                              ),\n                            ),\n                          ],\n                        ],\n                      ),\n                    ),\n                ],\n              ),\n            ),\n        ],\n      ),\n    );\n  }\n\n  IconData _getLinkIcon(String url, [IconData? icon]) {\n    final uri = Uri.parse(url);\n    final host = uri.host.toLowerCase();\n\n    if (host.endsWith('telegram.me') || host.endsWith('t.me')) {\n      return FontAwesomeIcons.telegram;\n    }\n    if (host.endsWith('instagram.com')) {\n      return FontAwesomeIcons.instagram;\n    }\n    if (host.endsWith('twitter.com')) {\n      return FontAwesomeIcons.xTwitter;\n    }\n    if (host.endsWith('facebook.com')) {\n      return FontAwesomeIcons.facebook;\n    }\n    if (host.endsWith('hiddify.com')) {\n      // return IconData();\n    }\n    return icon ?? FluentIcons.link_24_regular;\n  }\n\n  String _formatSupportLink(String url) {\n    final uri = Uri.parse(url);\n    final host = uri.host.toLowerCase();\n\n    if (host.endsWith('telegram.me') || host.endsWith('t.me')) {\n      return \"@${uri.pathSegments.last}\";\n    }\n    if (host.endsWith('instagram.com')) {\n      return \"@${uri.pathSegments.first}\";\n    }\n    if (host.endsWith('twitter.com')) {\n      return \"@${uri.pathSegments.first}\";\n    }\n    if (host.endsWith('facebook.com')) {\n      return uri.pathSegments.lastWhere((e) => e.isNotEmpty, orElse: () => '');\n    }\n    if (host.endsWith('hiddify.com')) {\n      return \"Hiddify\";\n    }\n    return uri.host;\n  }\n\n  Color _getProgressColor(double ratio) {\n    if (ratio < 0.25) return Colors.red;\n    if (ratio < 0.45) return Colors.orange;\n    return Colors.green;\n  }\n\n  Widget _BandwithUsageRow(SubscriptionInfo subInfo) {\n    return _UsageRow(\n      icon: FluentIcons.data_usage_24_filled,\n      title: subInfo.total.isInfinitSize() ? \"∞ GB remaining\" : \"${subInfo.remainingBWratio * 100}% remaining\",\n      progress: subInfo.total.isInfinitSize() ? 1 : subInfo.remainingBWratio,\n      color: _getProgressColor(subInfo.remainingBWratio),\n    );\n  }\n}\n\n// Rest of the widget classes remain the same...\n\nclass _UsageRow extends StatelessWidget {\n  const _UsageRow({required this.icon, required this.title, required this.progress, required this.color});\n\n  final IconData? icon;\n  final String title;\n  final double progress;\n  final Color color;\n\n  @override\n  Widget build(BuildContext context) {\n    return Expanded(\n      child: Padding(\n        padding: const EdgeInsets.all(12),\n        child: Row(\n          children: [\n            if (icon != null) ...[Icon(icon, size: 20, color: color), const Gap(12)],\n            Expanded(\n              child: Column(\n                crossAxisAlignment: CrossAxisAlignment.start,\n                children: [\n                  Text(title, style: Theme.of(context).textTheme.bodyMedium),\n                  const Gap(4),\n                  ClipRRect(\n                    borderRadius: BorderRadius.circular(4),\n                    child: LinearProgressIndicator(\n                      value: progress,\n                      backgroundColor: Theme.of(context).colorScheme.surfaceVariant,\n                      valueColor: AlwaysStoppedAnimation<Color>(color),\n                      minHeight: 4,\n                    ),\n                  ),\n                ],\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n\nclass _InfoItem extends StatelessWidget {\n  const _InfoItem({required this.icon, required this.label, required this.value});\n\n  final IconData icon;\n  final String label;\n  final String value;\n\n  @override\n  Widget build(BuildContext context) {\n    final theme = Theme.of(context);\n\n    return Container(\n      padding: const EdgeInsets.all(12),\n      // decoration: BoxDecoration(\n      //   color: theme.colorScheme.surfaceVariant.withOpacity(0.5),\n      //   borderRadius: BorderRadius.circular(12),\n      // ),\n      child: Row(\n        children: [\n          Icon(icon, size: 20, color: theme.colorScheme.onSurfaceVariant),\n          const Gap(12),\n          Expanded(\n            child: Column(\n              crossAxisAlignment: CrossAxisAlignment.start,\n              children: [\n                Text(\n                  label,\n                  style: theme.textTheme.bodySmall?.copyWith(\n                    color: theme.colorScheme.onSurfaceVariant.withOpacity(0.7),\n                  ),\n                ),\n                Text(value, style: theme.textTheme.bodyMedium, maxLines: 1, overflow: TextOverflow.ellipsis),\n              ],\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/proxy/active/active_proxy_card.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/connection/model/connection_status.dart';\nimport 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/features/proxy/active/active_proxy_notifier.dart';\nimport 'package:hiddify/features/proxy/active/ip_widget.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ActiveProxyFooter extends ConsumerWidget with InfraLogger {\n  const ActiveProxyFooter({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final connectionState = ref.watch(\n      connectionNotifierProvider.select((value) => value.valueOrNull ?? const Disconnected()),\n    );\n\n    final activeProxy = ref.watch(activeProxyNotifierProvider.select((value) => value.valueOrNull));\n    final t = ref.watch(translationsProvider).requireValue;\n\n    // Early return if required data is not available\n    if (connectionState != const Connected() || activeProxy == null) {\n      return const SizedBox.shrink();\n    }\n\n    final theme = Theme.of(context);\n\n    // Handle URL test in a way that won't trigger during build\n    Future<void> handleUrlTest() async {\n      try {\n        if (!context.mounted) return;\n        await ref.read(activeProxyNotifierProvider.notifier).urlTest(\"\");\n      } catch (e) {\n        // Handle error here\n        loggy.error(\"Error during URL test: $e\");\n      }\n    }\n\n    return Container(\n      margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),\n      padding: const EdgeInsets.symmetric(vertical: 12),\n      decoration: BoxDecoration(\n        color: theme.colorScheme.background.withOpacity(1),\n        borderRadius: BorderRadius.circular(20),\n        boxShadow: [\n          BoxShadow(color: theme.colorScheme.secondary.withOpacity(.21), blurRadius: 10, offset: const Offset(0, 4)),\n        ],\n      ),\n      child: InkWell(\n        onTap: () {\n          context.goNamed('proxies');\n        },\n        child: Row(\n          children: [\n            InkWell(\n              onTap: () async {\n                await handleUrlTest();\n                await ref.read(dialogNotifierProvider.notifier).showProxyInfo(outboundInfo: activeProxy);\n              },\n              child: Padding(\n                padding: const EdgeInsets.symmetric(horizontal: 8),\n                child: IPCountryFlag(\n                  countryCode: activeProxy.ipinfo.countryCode,\n                  organization: activeProxy.ipinfo.org,\n                  size: 48,\n                ),\n              ),\n            ),\n            Expanded(\n              child: Column(\n                mainAxisAlignment: MainAxisAlignment.center,\n                crossAxisAlignment: CrossAxisAlignment.start,\n                children: [\n                  Semantics(\n                    label: t.pages.proxies.activeProxy,\n                    child: Text(\n                      // getRealOutboundTag(activeProxy),\n                      activeProxy.tagDisplay,\n                      style: theme.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.bold),\n                      maxLines: 1,\n                      overflow: TextOverflow.ellipsis,\n                    ),\n                  ),\n                  const SizedBox(height: 4),\n                  Row(\n                    children: [\n                      if (activeProxy.ipinfo.ip.isNotEmpty)\n                        IPText(ip: activeProxy.ipinfo.ip, onLongPress: handleUrlTest, constrained: true)\n                      else\n                        UnknownIPText(text: t.pages.proxies.unknownIp, onTap: handleUrlTest),\n                      const Spacer(),\n                      Text(\n                        // getRealOutboundTag(activeProxy),\n                        activeProxy.type,\n                        style: theme.textTheme.bodySmall?.copyWith(fontWeight: FontWeight.bold),\n                        maxLines: 1,\n                        overflow: TextOverflow.ellipsis,\n                      ),\n                    ],\n                  ),\n                ],\n              ),\n            ),\n            const Padding(\n              padding: EdgeInsets.all(16.0),\n              child: Icon(Icons.arrow_forward_ios, color: Colors.blue),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n\nString getRealOutboundTag(OutboundInfo group) {\n  var tag = group.tagDisplay;\n  if (group.groupSelectedTagDisplay != \"\" && group.groupSelectedTagDisplay != tag) {\n    tag = \"$tag → ${group.groupSelectedTagDisplay}\";\n  }\n  return tag;\n}\n\n// class _StatsColumn extends HookConsumerWidget {\n//   const _StatsColumn();\n\n//   @override\n//   Widget build(BuildContext context, WidgetRef ref) {\n//     final t = ref.watch(translationsProvider).requireValue;\n//     final stats = ref.watch(statsNotifierProvider).value;\n\n//     return Directionality(\n//       textDirection: TextDirection.values[(Directionality.of(context).index + 1) % TextDirection.values.length],\n//       child: Flexible(\n//         child: Column(\n//           children: [\n//             _InfoProp(\n//               icon: FluentIcons.arrow_bidirectional_up_down_20_regular,\n//               text: (stats?.downlinkTotal ?? 0).size(),\n//               semanticLabel: t.stats.totalTransferred,\n//             ),\n//             const Gap(8),\n//             _InfoProp(\n//               icon: FluentIcons.arrow_download_20_regular,\n//               text: (stats?.downlink ?? 0).speed(),\n//               semanticLabel: t.stats.speed,\n//             ),\n//           ],\n//         ),\n//       ),\n//     );\n//   }\n// }\n\n// class _InfoProp extends StatelessWidget {\n//   const _InfoProp({\n//     required this.icon,\n//     required this.text,\n//     this.semanticLabel,\n//   });\n\n//   final IconData icon;\n//   final String text;\n//   final String? semanticLabel;\n\n//   @override\n//   Widget build(BuildContext context) {\n//     return Semantics(\n//       label: semanticLabel,\n//       child: Row(\n//         children: [\n//           Icon(icon),\n//           const Gap(8),\n//           Flexible(\n//             child: Text(\n//               text,\n//               style: Theme.of(context).textTheme.labelMedium?.copyWith(fontFamily: FontFamily.emoji),\n//               overflow: TextOverflow.ellipsis,\n//             ),\n//           ),\n//         ],\n//       ),\n//     );\n//   }\n// }\n"
  },
  {
    "path": "lib/features/proxy/active/active_proxy_delay_indicator.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/widget/shimmer_skeleton.dart';\nimport 'package:hiddify/features/proxy/active/active_proxy_notifier.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ActiveProxyDelayIndicator extends HookConsumerWidget with InfraLogger {\n  const ActiveProxyDelayIndicator({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final activeProxy = ref.watch(activeProxyNotifierProvider);\n    final theme = Theme.of(context);\n\n    if (activeProxy is! AsyncData) {\n      return const SizedBox(); // Avoid building widget if data is not available\n    }\n\n    final proxy = activeProxy.value!;\n    final delay = proxy.urlTestDelay;\n    final timeout = delay > 65000;\n\n    return Center(\n      child: InkWell(\n        onTap: () async {\n          try {\n            await ref.read(activeProxyNotifierProvider.notifier).urlTest(\"\");\n          } catch (e) {\n            // Handle error here\n            loggy.error(\"Error during URL test: $e\");\n          }\n        },\n        borderRadius: BorderRadius.circular(24),\n        child: Padding(\n          padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),\n          child: Row(\n            mainAxisSize: MainAxisSize.min,\n            children: [\n              const Icon(FluentIcons.wifi_1_24_regular),\n              const Gap(8),\n              if (delay > 0)\n                Text.rich(\n                  semanticsLabel: timeout ? t.pages.proxies.delay.timeout : t.pages.proxies.delay.result(delay: delay),\n                  TextSpan(\n                    children: [\n                      if (timeout)\n                        TextSpan(\n                          text: t.common.timeout,\n                          style: theme.textTheme.titleMedium?.copyWith(\n                            fontWeight: FontWeight.bold,\n                            color: theme.colorScheme.error,\n                          ),\n                        )\n                      else ...[\n                        TextSpan(\n                          text: delay.toString(),\n                          style: theme.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),\n                        ),\n                        const TextSpan(text: \" ms\"),\n                      ],\n                    ],\n                  ),\n                )\n              else\n                Semantics(label: t.pages.proxies.delay.testing, child: const ShimmerSkeleton(width: 48, height: 18)),\n            ],\n          ),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/proxy/active/active_proxy_footer_old.dart",
    "content": "// class ActiveProxyFooter extends HookConsumerWidget {\n//   const ActiveProxyFooter({super.key});\n\n//   @override\n//   Widget build(BuildContext context, WidgetRef ref) {\n//     return Column();\n//     final t = ref.watch(translationsProvider).requireValue;\n//     final activeProxy = ref.watch(activeProxyNotifierProvider);\n//     // final ipInfo = ref.watch(ipInfoNotifierProvider);\n\n//     return AnimatedVisibility(\n//       axis: Axis.vertical,\n//       visible: activeProxy is AsyncData,\n//       child: switch (activeProxy) {\n//         AsyncData(value: final proxy) => Padding(\n//             padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),\n//             child: Row(\n//               mainAxisAlignment: MainAxisAlignment.spaceBetween,\n//               children: [\n//                 Flexible(\n//                   child: Column(\n//                     crossAxisAlignment: CrossAxisAlignment.start,\n//                     children: [\n//                       _InfoProp(\n//                         icon: FluentIcons.arrow_routing_20_regular,\n//                         text: proxy.tagDisplay,\n//                         semanticLabel: t.proxies.activeProxySemanticLabel,\n//                       ),\n//                       const Gap(8),\n//                       if (proxy.ipinfo.ip.isNotEmpty)\n//                         Row(\n//                           children: [\n//                             IPCountryFlag(countryCode: proxy.ipinfo.countryCode),\n//                             const Gap(4),\n//                             OrganisationFlag(organization: proxy.ipinfo.org),\n//                             const Gap(4),\n//                             IPText(\n//                               ip: proxy.ipinfo.ip,\n//                               onLongPress: () async {\n//                                 ref.read(ipInfoNotifierProvider.notifier).refresh();\n//                               },\n//                             ),\n//                             // const Gap(8),\n//                           ],\n//                         )\n//                       else\n//                         Row(\n//                           children: [\n//                             const Icon(FluentIcons.arrow_sync_20_regular),\n//                             const Gap(8),\n//                             UnknownIPText(\n//                               text: t.proxies.checkIp,\n//                               onTap: () async {\n//                                 ref.read(ipInfoNotifierProvider.notifier).refresh();\n//                               },\n//                             ),\n//                           ],\n//                         ),\n//                       // switch (ipInfo) {\n//                       //   AsyncData(value: final info) => Row(\n//                       //       children: [\n//                       //         IPCountryFlag(countryCode: info.countryCode),\n//                       //         const Gap(4),\n//                       //         OrganisationFlag(organization: info.org ?? \"\"),\n//                       //         const Gap(4),\n//                       //         IPText(\n//                       //           ip: info.ip,\n//                       //           onLongPress: () async {\n//                       //             ref.read(ipInfoNotifierProvider.notifier).refresh();\n//                       //           },\n//                       //         ),\n//                       //         // const Gap(8),\n//                       //       ],\n//                       //     ),\n//                       //   AsyncError(error: final UnknownIp _) => Row(\n//                       //       children: [\n//                       //         const Icon(FluentIcons.arrow_sync_20_regular),\n//                       //         const Gap(8),\n//                       //         UnknownIPText(\n//                       //           text: t.proxies.checkIp,\n//                       //           onTap: () async {\n//                       //             ref.read(ipInfoNotifierProvider.notifier).refresh();\n//                       //           },\n//                       //         ),\n//                       //       ],\n//                       //     ),\n//                       //   AsyncError() => Row(\n//                       //       children: [\n//                       //         const Icon(FluentIcons.error_circle_20_regular),\n//                       //         const Gap(8),\n//                       //         UnknownIPText(\n//                       //           text: t.proxies.unknownIp,\n//                       //           onTap: () async {\n//                       //             ref.read(ipInfoNotifierProvider.notifier).refresh();\n//                       //           },\n//                       //         ),\n//                       //       ],\n//                       //     ),\n//                       //   _ => const Row(\n//                       //       children: [\n//                       //         Icon(FluentIcons.question_circle_20_regular),\n//                       //         Gap(8),\n//                       //         Flexible(\n//                       //           child: ShimmerSkeleton(\n//                       //             height: 16,\n//                       //             widthFactor: 1,\n//                       //           ),\n//                       //         ),\n//                       //       ],\n//                       //     ),\n//                       // },\n//                     ],\n//                   ),\n//                 ),\n//                 const _StatsColumn(),\n//               ],\n//             ),\n//           ),\n//         _ => const SizedBox(),\n//       },\n//     );\n//   }\n// }\n\n// class _StatsColumn extends HookConsumerWidget {\n//   const _StatsColumn();\n\n//   @override\n//   Widget build(BuildContext context, WidgetRef ref) {\n//     final t = ref.watch(translationsProvider).requireValue;\n//     final stats = ref.watch(statsNotifierProvider).value;\n\n//     return Directionality(\n//       textDirection: TextDirection.values[(Directionality.of(context).index + 1) % TextDirection.values.length],\n//       child: Flexible(\n//         child: Column(\n//           children: [\n//             _InfoProp(\n//               icon: FluentIcons.arrow_bidirectional_up_down_20_regular,\n//               text: (stats?.downlinkTotal.toInt() ?? 0).size(),\n//               semanticLabel: t.stats.totalTransferred,\n//             ),\n//             const Gap(8),\n//             _InfoProp(\n//               icon: FluentIcons.arrow_download_20_regular,\n//               text: (stats?.downlink.toInt() ?? 0).speed(),\n//               semanticLabel: t.stats.speed,\n//             ),\n//           ],\n//         ),\n//       ),\n//     );\n//   }\n// }\n\n// class _InfoProp extends StatelessWidget {\n//   const _InfoProp({\n//     required this.icon,\n//     required this.text,\n//     this.semanticLabel,\n//   });\n\n//   final IconData icon;\n//   final String text;\n//   final String? semanticLabel;\n\n//   @override\n//   Widget build(BuildContext context) {\n//     return Semantics(\n//       label: semanticLabel,\n//       child: Row(\n//         children: [\n//           Icon(icon),\n//           const Gap(8),\n//           Flexible(\n//             child: Text(\n//               text,\n//               style: Theme.of(context).textTheme.labelMedium?.copyWith(fontFamily: FontFamily.emoji),\n//               overflow: TextOverflow.ellipsis,\n//             ),\n//           ),\n//         ],\n//       ),\n//     );\n//   }\n// }\n"
  },
  {
    "path": "lib/features/proxy/active/active_proxy_notifier.dart",
    "content": "import 'dart:async';\n\nimport 'package:dio/dio.dart';\nimport 'package:hiddify/core/haptic/haptic_service.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/utils/throttler.dart';\nimport 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/features/proxy/data/proxy_data_providers.dart';\nimport 'package:hiddify/features/proxy/model/ip_info_entity.dart' as oldipinfo;\nimport 'package:hiddify/features/proxy/model/proxy_failure.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/hiddifycore/init_signal.dart';\nimport 'package:hiddify/utils/riverpod_utils.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'active_proxy_notifier.g.dart';\n\n@riverpod\nclass IpInfoNotifier extends _$IpInfoNotifier with AppLogger {\n  @override\n  Future<oldipinfo.IpInfo> build() async {\n    ref.disposeDelay(const Duration(seconds: 20));\n    final cancelToken = CancelToken();\n    Timer? timer;\n    ref.onDispose(() {\n      loggy.debug(\"disposing\");\n      cancelToken.cancel();\n      timer?.cancel();\n    });\n\n    ref.listen(serviceRunningProvider, (_, next) => _idle = false);\n\n    final autoCheck = ref.watch(Preferences.autoCheckIp);\n    final serviceRunning = await ref.watch(serviceRunningProvider.future);\n    // loggy.debug(\n    //   \"idle? [$_idle], forced? [$_forceCheck], connected? [$serviceRunning]\",\n    // );\n    if (!_forceCheck && !serviceRunning) {\n      throw const ServiceNotRunning();\n    } else if ((_idle && !_forceCheck) || (!_forceCheck && serviceRunning && !autoCheck)) {\n      throw const UnknownIp();\n    }\n\n    _forceCheck = false;\n    final info = await ref.watch(proxyRepositoryProvider).getCurrentIpInfo(cancelToken).getOrElse((err) {\n      loggy.warning(\"error getting proxy ip info\", err, StackTrace.current);\n      // throw err; //hiddify: remove exception to be logged\n      throw const UnknownIp();\n    }).run();\n\n    timer = Timer(const Duration(seconds: 10), () {\n      loggy.debug(\"entering idle mode\");\n      _idle = true;\n      ref.invalidateSelf();\n    });\n\n    return info;\n  }\n\n  bool _idle = false;\n  bool _forceCheck = false;\n\n  Future<void> refresh() async {\n    if (state.isLoading) return;\n    loggy.debug(\"refreshing\");\n    state = const AsyncLoading();\n    await ref.read(hapticServiceProvider.notifier).lightImpact();\n    _forceCheck = true;\n    ref.invalidateSelf();\n  }\n}\n\n@Riverpod(keepAlive: true)\nclass ActiveProxyNotifier extends _$ActiveProxyNotifier with AppLogger {\n  @override\n  Stream<OutboundInfo> build() async* {\n    // ref.disposeDelay(const Duration(seconds: 20));\n    ref.watch(coreRestartSignalProvider);\n    final serviceRunning = await ref.watch(serviceRunningProvider.future);\n    if (!serviceRunning) {\n      throw const ServiceNotRunning();\n    }\n    final proxyprovider = ref.watch(proxyRepositoryProvider);\n    yield* proxyprovider\n        .watchActiveProxies()\n        .map((event) => event.getOrElse((l) => List<OutboundGroup>.empty()))\n        .map((event) => event.firstOrNull?.items.first ?? OutboundInfo());\n  }\n\n  final _urlTestThrottler = Throttler(const Duration(seconds: 1));\n\n  Future<void> urlTest(String? groupTag_) async {\n    final groupTag = groupTag_ ?? \"\";\n    _urlTestThrottler(() async {\n      if (state case AsyncData()) {\n        await ref.read(hapticServiceProvider.notifier).lightImpact();\n        await ref.read(proxyRepositoryProvider).urlTest(groupTag).getOrElse((err) {\n          loggy.warning(\"error testing group\", err);\n          throw err;\n        }).run();\n      }\n    });\n  }\n}\n"
  },
  {
    "path": "lib/features/proxy/active/ip_widget.dart",
    "content": "import 'package:circle_flags/circle_flags.dart';\nimport 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:hiddify/core/haptic/haptic_service.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/utils/ip_utils.dart';\nimport 'package:hiddify/gen/fonts.gen.dart';\nimport 'package:hiddify/utils/riverpod_utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport \"package:simple_icons/simple_icons.dart\";\n\nfinal _showIp = StateProvider.autoDispose((ref) {\n  ref.disposeDelay(const Duration(seconds: 20));\n  ref.listenSelf((previous, next) {\n    if (previous == false && next == true) {\n      ref.read(hapticServiceProvider.notifier).mediumImpact();\n    }\n  });\n  return false;\n});\n\nclass IPText extends HookConsumerWidget {\n  const IPText({required this.ip, required this.onLongPress, this.constrained = false, super.key});\n\n  final String ip;\n  final VoidCallback onLongPress;\n  final bool constrained;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final isVisible = ref.watch(_showIp);\n    final textTheme = Theme.of(context).textTheme;\n    final ipStyle = (constrained ? textTheme.labelMedium : textTheme.labelLarge)?.copyWith(\n      fontFamily: FontFamily.emoji,\n    );\n\n    return Semantics(\n      label: t.pages.proxies.ipInfo.address,\n      child: InkWell(\n        onTap: () {\n          ref.read(_showIp.notifier).state = !isVisible;\n        },\n        onLongPress: onLongPress,\n        borderRadius: BorderRadius.circular(12),\n        child: Padding(\n          padding: const EdgeInsets.symmetric(horizontal: 2),\n          child: AnimatedCrossFade(\n            firstChild: Text(ip, style: ipStyle, textDirection: TextDirection.ltr, overflow: TextOverflow.ellipsis),\n            secondChild: Padding(\n              padding: constrained ? EdgeInsets.zero : const EdgeInsetsDirectional.only(end: 48),\n              child: Text(\n                obscureIp(ip),\n                semanticsLabel: t.common.hidden,\n                style: ipStyle,\n                textDirection: TextDirection.ltr,\n                overflow: TextOverflow.ellipsis,\n              ),\n            ),\n            crossFadeState: isVisible ? CrossFadeState.showFirst : CrossFadeState.showSecond,\n            duration: const Duration(milliseconds: 200),\n          ),\n        ),\n      ),\n    );\n  }\n}\n\nclass UnknownIPText extends HookConsumerWidget {\n  const UnknownIPText({required this.text, required this.onTap, this.constrained = false, super.key});\n\n  final String text;\n  final VoidCallback onTap;\n  final bool constrained;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final textTheme = Theme.of(context).textTheme;\n    final style = constrained ? textTheme.bodySmall : textTheme.labelMedium;\n\n    return Semantics(\n      label: t.pages.proxies.ipInfo.address,\n      child: InkWell(\n        onTap: onTap,\n        borderRadius: BorderRadius.circular(12),\n        child: Padding(\n          padding: const EdgeInsets.symmetric(horizontal: 2),\n          child: Text(text, style: style, overflow: TextOverflow.ellipsis),\n        ),\n      ),\n    );\n  }\n}\n\nclass IPCountryFlag extends HookConsumerWidget {\n  const IPCountryFlag({\n    required this.countryCode,\n    this.organization,\n    this.size = 16,\n    this.padding = EdgeInsets.zero,\n    super.key,\n  });\n\n  final String? countryCode;\n  final double size;\n\n  final EdgeInsetsGeometry padding;\n\n  final String? organization;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return Semantics(\n      label: t.pages.proxies.ipInfo.country,\n      child: Padding(\n        padding: padding,\n        child: (countryCode?.isEmpty ?? true)\n            ? Icon(FluentIcons.question_circle_20_regular, size: size)\n            : SizedBox(\n                width: size,\n                height: size,\n                child: Stack(\n                  textDirection: Directionality.of(context),\n                  alignment: Alignment.center,\n                  children: [\n                    CircleFlag(\n                      // key: ValueKey(countryCode),\n                      countryCode!.toLowerCase() == \"ir\" ? \"ir-shir\" : countryCode!,\n                      size: size - 8,\n                      shape: RoundedRectangleBorder(\n                        borderRadius: BorderRadius.circular(8), // Rounded effect\n                      ),\n                    ),\n                    if (organization != null)\n                      Positioned.directional(\n                        textDirection: Directionality.of(context),\n                        bottom: 0,\n                        end: 0,\n                        child: OrganisationFlag(organization: organization!, size: size / 2.5),\n                      ),\n                  ],\n                ),\n              ),\n      ),\n    );\n  }\n}\n\nclass OrgIconData {\n  final IconData icon;\n  final Color color;\n\n  const OrgIconData(this.icon, this.color);\n}\n\n// Map of organization keywords to icon and color\nconst Map<String, OrgIconData> organizationData = {\n  \"cloudflare\": OrgIconData(SimpleIcons.cloudflare, SimpleIconColors.cloudflare),\n  \"hetzner\": OrgIconData(SimpleIcons.hetzner, SimpleIconColors.hetzner),\n  \"ovh\": OrgIconData(SimpleIcons.ovh, SimpleIconColors.ovh),\n  \"azure\": OrgIconData(SimpleIcons.microsoftazure, SimpleIconColors.microsoftazure),\n  \"amazon\": OrgIconData(SimpleIcons.amazonaws, SimpleIconColors.amazonaws),\n  \"oracle\": OrgIconData(SimpleIcons.oracle, SimpleIconColors.oracle),\n  \"fastly\": OrgIconData(SimpleIcons.fastly, SimpleIconColors.fastly),\n  \"digitalocean\": OrgIconData(SimpleIcons.digitalocean, SimpleIconColors.digitalocean),\n  \"alibaba\": OrgIconData(SimpleIcons.alibabacloud, SimpleIconColors.alibabacloud),\n  \"google\": OrgIconData(SimpleIcons.googlecloud, SimpleIconColors.googlecloud),\n  \"starlink\": OrgIconData(SimpleIcons.satellite, SimpleIconColors.satellite),\n};\n\nclass OrganisationFlag extends HookConsumerWidget {\n  const OrganisationFlag({required this.organization, this.size = 24, super.key});\n\n  final String organization;\n  final double size;\n\n  // Function to create flag widget with icon and color\n  Widget getFlagWidget({\n    required Widget widget,\n    required String organization,\n    required double size,\n    required String label,\n    required Color color,\n  }) {\n    return Semantics(\n      label: \"$label $organization\",\n      child: Container(\n        width: size,\n        height: size,\n\n        decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(100)),\n        // padding: const ,\n        child: widget,\n      ),\n    );\n  }\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    for (final entry in organizationData.entries) {\n      if (organization.toLowerCase().contains(entry.key)) {\n        return getFlagWidget(\n          widget: Icon(entry.value.icon, color: Colors.white, size: size - 6),\n          color: entry.value.color,\n          organization: organization,\n          size: size,\n          label: t.pages.proxies.ipInfo.organization,\n        );\n      }\n    }\n\n    // Return empty widget if no match is found\n    return const SizedBox.shrink();\n  }\n}\n"
  },
  {
    "path": "lib/features/proxy/data/proxy_data_providers.dart",
    "content": "import 'package:hiddify/core/http_client/http_client_provider.dart';\nimport 'package:hiddify/features/proxy/data/proxy_repository.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service_provider.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'proxy_data_providers.g.dart';\n\n@Riverpod(keepAlive: true)\nProxyRepository proxyRepository(Ref ref) {\n  return ProxyRepositoryImpl(singbox: ref.watch(hiddifyCoreServiceProvider), client: ref.watch(httpClientProvider));\n}\n"
  },
  {
    "path": "lib/features/proxy/data/proxy_repository.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/http_client/dio_http_client.dart';\nimport 'package:hiddify/core/utils/exception_handler.dart';\nimport 'package:hiddify/features/proxy/model/ip_info_entity.dart' as oldipinfo;\n\nimport 'package:hiddify/features/proxy/model/proxy_failure.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\n\nabstract interface class ProxyRepository {\n  // Stream<Either<ProxyFailure, List<OutboundGroup>>> watchProxies();\n  Stream<Either<ProxyFailure, OutboundGroup?>> watchProxies();\n  Stream<Either<ProxyFailure, List<OutboundGroup>>> watchActiveProxies();\n  TaskEither<ProxyFailure, oldipinfo.IpInfo> getCurrentIpInfo(CancelToken cancelToken);\n  TaskEither<ProxyFailure, Unit> selectProxy(String groupTag, String outboundTag);\n  TaskEither<ProxyFailure, Unit> urlTest(String groupTag);\n}\n\nclass ProxyRepositoryImpl with ExceptionHandler, InfraLogger implements ProxyRepository {\n  ProxyRepositoryImpl({required this.singbox, required this.client});\n\n  final HiddifyCoreService singbox;\n  final DioHttpClient client;\n\n  // @override\n  // Stream<Either<ProxyFailure, List<OutboundGroup>>> watchProxies() {\n  //   return singbox.watchGroups().map((event) {\n  //     // final groupWithSelected = {\n  //     //   for (final group in event) group.tag: group.selected,\n  //     // };\n\n  //     return event;\n  //     // .map(\n  //     //   (e) => ProxyGroupEntity(\n  //     //     tag: e.tag,\n  //     //     type: e.type,\n  //     //     selected: e.selected,\n  //     //     items: e.items\n  //     //         .map(\n  //     //           (e) => ProxyItemEntity(\n  //     //             tag: e.tag,\n  //     //             type: e.type,\n  //     //             urlTestDelay: e.urlTestDelay,\n  //     //             selectedTag: groupWithSelected[e.tag],\n  //     //           ),\n  //     //         )\n  //     //         .filter((t) => t.isVisible)\n  //     //         .toList(),\n  //     //   ),\n  //     // )\n  //     // .toList();\n  //   }).handleExceptions(\n  //     (error, stackTrace) {\n  //       loggy.error(\"error watching proxies\", error, stackTrace);\n  //       return ProxyUnexpectedFailure(error, stackTrace);\n  //     },\n  //   );\n  // }\n\n  @override\n  Stream<Either<ProxyFailure, OutboundGroup?>> watchProxies() {\n    return singbox.watchGroup().handleExceptions((error, stackTrace) {\n      loggy.error(\"error watching proxies\", error, stackTrace);\n      return ProxyUnexpectedFailure(error, stackTrace);\n    });\n  }\n\n  @override\n  Stream<Either<ProxyFailure, List<OutboundGroup>>> watchActiveProxies() {\n    return singbox.watchActiveGroups().handleExceptions((error, stackTrace) {\n      loggy.error(\"error watching active proxies\", error, stackTrace);\n      return ProxyUnexpectedFailure(error, stackTrace);\n    });\n  }\n\n  @override\n  TaskEither<ProxyFailure, Unit> selectProxy(String groupTag, String outboundTag) {\n    return exceptionHandler(\n      () => singbox.selectOutbound(groupTag, outboundTag).mapLeft(ProxyUnexpectedFailure.new).run(),\n      ProxyUnexpectedFailure.new,\n    );\n  }\n\n  @override\n  TaskEither<ProxyFailure, Unit> urlTest(String groupTag) {\n    return exceptionHandler(\n      () => singbox.urlTest(groupTag).mapLeft(ProxyUnexpectedFailure.new).run(),\n      ProxyUnexpectedFailure.new,\n    );\n  }\n\n  static final Map<String, oldipinfo.IpInfo Function(Map<String, dynamic> response)> _ipInfoSources = {\n    // \"https://geolocation-db.com/json/\": IpInfo.fromGeolocationDbComJson, //bug response is not json\n    \"https://ipwho.is/\": oldipinfo.IpInfo.fromIpwhoIsJson,\n    \"https://api.ip.sb/geoip/\": oldipinfo.IpInfo.fromIpSbJson,\n    \"https://ipapi.co/json/\": oldipinfo.IpInfo.fromIpApiCoJson,\n    \"https://ipinfo.io/json/\": oldipinfo.IpInfo.fromIpInfoIoJson,\n  };\n\n  @override\n  TaskEither<ProxyFailure, oldipinfo.IpInfo> getCurrentIpInfo(CancelToken cancelToken) {\n    return TaskEither.tryCatch(() async {\n      Object? error;\n      for (final source in _ipInfoSources.entries) {\n        try {\n          loggy.debug(\"getting current ip info using [${source.key}]\");\n          final response = await client.get<Map<String, dynamic>>(\n            source.key,\n            cancelToken: cancelToken,\n            proxyOnly: true,\n          );\n          if (response.statusCode == 200 && response.data != null) {\n            return source.value(response.data!);\n          }\n        } catch (e, s) {\n          loggy.debug(\"failed getting ip info using [${source.key}]\", e, s);\n          error = e;\n          continue;\n        }\n      }\n      throw UnableToRetrieveIp(error, StackTrace.current);\n    }, ProxyUnexpectedFailure.new);\n  }\n}\n"
  },
  {
    "path": "lib/features/proxy/model/ip_info_entity.dart",
    "content": "import 'package:dart_mappable/dart_mappable.dart';\n\npart 'ip_info_entity.mapper.dart';\n\n@MappableClass()\nclass IpInfo with IpInfoMappable {\n  const IpInfo({\n    required this.ip,\n    required this.countryCode,\n    this.region,\n    this.city,\n    this.timezone,\n    this.asn,\n    this.org,\n  });\n\n  final String ip;\n  final String countryCode;\n  final String? region;\n  final String? city;\n  final String? timezone;\n  final String? asn;\n  final String? org;\n\n  static IpInfo fromIpInfoIoJson(Map<String, dynamic> json) {\n    return switch (json) {\n      {\n        \"ip\": final String ip,\n        \"country\": final String country,\n        // \"region\": final String region, //sometime is not available\n        // \"city\": final String city,//sometime is not available\n        \"timezone\": final String timezone,\n        \"org\": final String org,\n      } =>\n        IpInfo(\n          ip: ip,\n          countryCode: country,\n          // region: region,\n          // city: city,\n          timezone: timezone,\n          org: org,\n        ),\n      _ => throw const FormatException(\"invalid json\"),\n    };\n  }\n\n  static IpInfo fromIpApiCoJson(Map<String, dynamic> json) {\n    return switch (json) {\n      {\n        \"ip\": final String ip,\n        \"country_code\": final String countryCode,\n        // \"region\": final String region, //sometime is not available\n        // \"city\": final String city,//sometime is not available\n        \"timezone\": final String timezone,\n        \"asn\": final String asn,\n        \"org\": final String org,\n      } =>\n        IpInfo(\n          ip: ip,\n          countryCode: countryCode,\n          // region: region,\n          // city: city,\n          timezone: timezone,\n          asn: asn,\n          org: org,\n        ),\n      _ => throw const FormatException(\"invalid json\"),\n    };\n  }\n\n  static IpInfo fromIpSbJson(Map<String, dynamic> json) {\n    return switch (json) {\n      {\n        \"ip\": final String ip,\n        \"country_code\": final String countryCode,\n        // \"region\": final String region,\n        // \"city\": final String city,\n        \"timezone\": final String timezone,\n        \"asn\": final int asn,\n        \"asn_organization\": final String org,\n      } =>\n        IpInfo(\n          ip: ip,\n          countryCode: countryCode,\n          // region: region,\n          // city: city,\n          timezone: timezone,\n          asn: '$asn',\n          org: org,\n        ),\n      _ => throw const FormatException(\"invalid json\"),\n    };\n  }\n\n  static IpInfo fromIpwhoIsJson(Map<String, dynamic> json) {\n    return switch (json) {\n      {\n        \"ip\": final String ip,\n        \"country_code\": final String countryCode,\n        // \"region\": final String region,\n        // \"city\": final String city,\n        // \"timezone\": final String timezone,\n        // \"asn\": final int asn,\n        \"connection\": final Map<String, dynamic> connection,\n      } =>\n        IpInfo(\n          ip: ip,\n          countryCode: countryCode,\n          // region: region,\n          // city: city,\n          // timezone: timezone,\n          asn: '$connection[\"asn\"]',\n          org: '$connection[\"org\"]',\n        ),\n      _ => throw const FormatException(\"invalid json\"),\n    };\n  }\n\n  static IpInfo fromGeolocationDbComJson(Map<String, dynamic> json) {\n    return switch (json) {\n      {\n        \"ip\": final String ip,\n        \"country_code\": final String countryCode,\n        // \"state\": final String region,\n        \"city\": final String city,\n      } =>\n        IpInfo(\n          ip: ip,\n          countryCode: countryCode,\n          // region: region,\n          city: city,\n        ),\n      _ => throw const FormatException(\"invalid json\"),\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/proxy/model/proxy_entity.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/singbox/model/singbox_proxy_type.dart';\n\npart 'proxy_entity.freezed.dart';\n\n@freezed\nclass ProxyGroupEntity with _$ProxyGroupEntity {\n  const ProxyGroupEntity._();\n\n  const factory ProxyGroupEntity({\n    required String tag,\n    required String type,\n    required String selected,\n    @Default([]) List<ProxyItemEntity> items,\n  }) = _ProxyGroupEntity;\n\n  String get name => _sanitizedTag(tag);\n}\n\n@freezed\nclass ProxyItemEntity with _$ProxyItemEntity {\n  const ProxyItemEntity._();\n\n  const factory ProxyItemEntity({\n    required String tag,\n    required String type,\n    required int urlTestDelay,\n    String? selectedTag,\n  }) = _ProxyItemEntity;\n\n  String get name => _sanitizedTag(tag);\n  String? get selectedName => selectedTag == null ? null : _sanitizedTag(selectedTag!);\n  bool get isVisible => !tag.contains(\"§hide§\");\n}\n\nString _sanitizedTag(String tag) => tag.replaceFirst(RegExp(r\"\\§[^]*\"), \"\").trimRight();\n// bool get isVisible => !tag.contains(\"§hide§\");\n"
  },
  {
    "path": "lib/features/proxy/model/proxy_failure.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\n\npart 'proxy_failure.freezed.dart';\n\n@freezed\nsealed class ProxyFailure with _$ProxyFailure, Failure {\n  const ProxyFailure._();\n\n  @With<UnexpectedFailure>()\n  const factory ProxyFailure.unexpected([Object? error, StackTrace? stackTrace]) = ProxyUnexpectedFailure;\n\n  @With<ExpectedFailure>()\n  const factory ProxyFailure.serviceNotRunning() = ServiceNotRunning;\n\n  @With<ExpectedFailure>()\n  const factory ProxyFailure.unknownIp() = UnknownIp;\n\n  @With<ExpectedMeasuredFailure>()\n  const factory ProxyFailure.unableToRetrieveIp([Object? error, StackTrace? stackTrace]) = UnableToRetrieveIp;\n\n  @override\n  ({String type, String? message}) present(TranslationsEn t) {\n    return switch (this) {\n      ProxyUnexpectedFailure() => (type: t.errors.unexpected, message: null),\n      ServiceNotRunning() => (type: t.errors.singbox.serviceNotRunning, message: null),\n      UnknownIp() => (type: t.common.unknown, message: null),\n      UnableToRetrieveIp() => (type: t.errors.unexpected, message: null),\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/proxy/overview/proxies_overview_notifier.dart",
    "content": "import 'dart:async';\n\nimport 'package:dartx/dartx.dart';\n\nimport 'package:hiddify/core/haptic/haptic_service.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/core/utils/preferences_utils.dart';\nimport 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/features/proxy/data/proxy_data_providers.dart';\nimport 'package:hiddify/features/proxy/model/proxy_failure.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/hiddifycore/init_signal.dart';\nimport 'package:hiddify/utils/riverpod_utils.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'proxies_overview_notifier.g.dart';\n\nenum ProxiesSort {\n  unsorted,\n  name,\n  delay,\n  usage;\n\n  String present(TranslationsEn t) => switch (this) {\n    ProxiesSort.unsorted => t.pages.proxies.sortOptions.unsorted,\n    ProxiesSort.name => t.pages.proxies.sortOptions.name,\n    ProxiesSort.delay => t.pages.proxies.sortOptions.delay,\n    ProxiesSort.usage => t.pages.proxies.sortOptions.usage,\n  };\n}\n\n@Riverpod(keepAlive: true)\nclass ProxiesSortNotifier extends _$ProxiesSortNotifier with AppLogger {\n  late final _pref = PreferencesEntry(\n    preferences: ref.watch(sharedPreferencesProvider).requireValue,\n    key: \"proxies_sort_mode\",\n    defaultValue: ProxiesSort.delay,\n    mapFrom: ProxiesSort.values.byName,\n    mapTo: (value) => value.name,\n  );\n\n  @override\n  ProxiesSort build() {\n    final sortBy = _pref.read();\n    loggy.info(\"sort proxies by: [${sortBy.name}]\");\n    return sortBy;\n  }\n\n  Future<void> update(ProxiesSort value) {\n    state = value;\n    return _pref.write(value);\n  }\n}\n\n@riverpod\nclass ProxiesOverviewNotifier extends _$ProxiesOverviewNotifier with AppLogger {\n  @override\n  Stream<OutboundGroup?> build() async* {\n    ref.disposeDelay(const Duration(seconds: 15));\n    ref.watch(coreRestartSignalProvider);\n    final serviceRunning = await ref.watch(serviceRunningProvider.future);\n    if (!serviceRunning) {\n      throw const ServiceNotRunning();\n    }\n    final sortBy = ref.watch(proxiesSortNotifierProvider);\n    // yield* ref\n    //     .watch(proxyRepositoryProvider)\n    //     .watchProxies()\n    //     .throttleTime(\n    //       const Duration(milliseconds: 100),\n    //       leading: false,\n    //       trailing: true,\n    //     )\n    //     .map(\n    //       (event) => event.getOrElse(\n    //         (err) {\n    //           loggy.warning(\"error receiving proxies\", err);\n    //           throw err;\n    //         },\n    //       ),\n    //     )\n    //     .asyncMap((proxies) async => _sortOutbounds(proxies, sortBy));\n    yield* ref\n        .watch(proxyRepositoryProvider)\n        .watchProxies()\n        .map(\n          (event) => event.getOrElse((err) {\n            loggy.warning(\"error receiving proxies\", err);\n            throw err;\n          }),\n        )\n        .asyncMap((proxies) async => await _sortOutbounds(proxies, sortBy));\n  }\n\n  // Future<List<OutboundGroup>> _sortOutbounds(\n  //   List<OutboundGroup> proxies,\n  //   ProxiesSort sortBy,\n  // ) async {\n  //   final groupWithSelected = {\n  //     for (final o in proxies) o.tag: o.selected,\n  //   };\n  //   final sortedProxies = <OutboundGroup>[];\n  //   for (final group in proxies) {\n  //     final sortedItems = switch (sortBy) {\n  //       ProxiesSort.name => group.items.sortedWith((a, b) {\n  //           if (a.isGroup && !b.isGroup) return -1;\n  //           if (!a.isGroup && b.isGroup) return 1;\n  //           return a.tag.compareTo(b.tag);\n  //         }),\n  //       ProxiesSort.delay => group.items.sortedWith((a, b) {\n  //           if (a.isGroup && !b.isGroup) return -1;\n  //           if (!a.isGroup && b.isGroup) return 1;\n\n  //           final ai = a.urlTestDelay;\n  //           final bi = b.urlTestDelay;\n  //           if (ai == 0 && bi == 0) return -1;\n  //           if (ai == 0 && bi > 0) return 1;\n  //           if (ai > 0 && bi == 0) return -1;\n  //           return ai.compareTo(bi);\n  //         }),\n  //       ProxiesSort.unsorted => group.items,\n  //     };\n  //     final items = <OutboundInfo>[];\n  //     for (final item in sortedItems) {\n  //       // if (groupWithSelected.keys.contains(item.tag)) {\n  //       //   items.add(item.copyWith(selectedTag: groupWithSelected[item.tag]));\n  //       // } else {\n  //       items.add(item);\n  //       // }\n  //     }\n  //     group.items.clear();\n  //     group.items.addAll(items);\n  //     sortedProxies.add(group);\n  //   }\n  //   return sortedProxies;\n  // }\n\n  Future<OutboundGroup?> _sortOutbounds(OutboundGroup? proxies, ProxiesSort sortBy) async {\n    if (proxies == null) return null;\n\n    final sortedItems = switch (sortBy) {\n      ProxiesSort.name => proxies.items.sortedWith((a, b) {\n        if (a.isGroup && !b.isGroup) return -1;\n        if (!a.isGroup && b.isGroup) return 1;\n        return a.tag.compareTo(b.tag);\n      }),\n      ProxiesSort.delay => proxies.items.sortedWith((a, b) {\n        if (a.isGroup && !b.isGroup) return -1;\n        if (!a.isGroup && b.isGroup) return 1;\n\n        final ai = a.urlTestDelay;\n        final bi = b.urlTestDelay;\n        if (ai == 0 && bi == 0) return -1;\n        if (ai == 0 && bi > 0) return 1;\n        if (ai > 0 && bi == 0) return -1;\n        return ai.compareTo(bi);\n      }),\n      ProxiesSort.unsorted => proxies.items,\n      ProxiesSort.usage => proxies.items.sortedWith((a, b) {\n        if (a.isGroup && !b.isGroup) return -1;\n        if (!a.isGroup && b.isGroup) return 1;\n        return (b.upload + b.download).compareTo(a.upload + a.download);\n      }),\n    };\n    final items = <OutboundInfo>[];\n    for (final item in sortedItems) {\n      // if (groupWithSelected.keys.contains(item.tag)) {\n      //   items.add(item.copyWith(selectedTag: groupWithSelected[item.tag]));\n      // } else {\n      items.add(item);\n      // }\n    }\n    proxies.items.clear();\n    proxies.items.addAll(items);\n    return proxies;\n  }\n\n  // Future<void> changeProxy(String groupTag, String outboundTag) async {\n  //   loggy.debug(\n  //     \"changing proxy, group: [$groupTag] - outbound: [$outboundTag]\",\n  //   );\n  //   if (state case AsyncData(value: final outbounds)) {\n  //     await ref.read(hapticServiceProvider.notifier).lightImpact();\n  //     await ref.read(proxyRepositoryProvider).selectProxy(groupTag, outboundTag).getOrElse((err) {\n  //       loggy.warning(\"error selecting outbound\", err);\n  //       throw err;\n  //     }).run();\n  //     final outboundg = outbounds.where((e) => e.tag == groupTag).firstOrNull;\n  //     if (outboundg != null) {\n  //       final newselected = outboundg.items.where((e) => e.tag == outboundTag).firstOrNull;\n  //       if (newselected != null) {\n  //         newselected.isSelected = true;\n  //         outboundg.selected = newselected;\n  //       }\n  //     }\n  //     state = AsyncData(\n  //       [...outbounds],\n  //     ).copyWithPrevious(state);\n  //   }\n  // }\n\n  Future<void> changeProxy(String groupTag, String outboundTag) async {\n    loggy.debug(\"changing proxy, group: [$groupTag] - outbound: [$outboundTag]\");\n    if (!state.hasValue) return;\n    final outbounds = state.value!;\n    await ref.read(hapticServiceProvider.notifier).lightImpact();\n    await ref.read(proxyRepositoryProvider).selectProxy(groupTag, outboundTag).getOrElse((err) {\n      loggy.warning(\"error selecting outbound\", err);\n      throw err;\n    }).run();\n    final newselected = outbounds.items.where((e) => e.tag == outboundTag).firstOrNull;\n    if (newselected != null) {\n      newselected.isSelected = true;\n      outbounds.selected = newselected.tag;\n      state = AsyncValue.data(outbounds);\n    }\n  }\n\n  Future<void> urlTest(String groupTag) async {\n    loggy.debug(\"testing group: [$groupTag]\");\n    if (state case AsyncData()) {\n      await ref.read(hapticServiceProvider.notifier).lightImpact();\n      await ref.read(proxyRepositoryProvider).urlTest(groupTag).getOrElse((err) {\n        loggy.error(\"error testing group\", err);\n        throw err;\n      }).run();\n    }\n  }\n}\n"
  },
  {
    "path": "lib/features/proxy/overview/proxies_overview_page.dart",
    "content": "import 'dart:math';\n\nimport 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/features/proxy/overview/proxies_overview_notifier.dart';\nimport 'package:hiddify/features/proxy/widget/proxy_tile.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ProxiesOverviewPage extends HookConsumerWidget with PresLogger {\n  const ProxiesOverviewPage({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    final proxies = ref.watch(proxiesOverviewNotifierProvider);\n    final sortBy = ref.watch(proxiesSortNotifierProvider);\n\n    // final selectActiveProxyMutation = useMutation(\n    //   initialOnFailure: (error) => CustomToast.error(t.presentShortError(error)).show(context),\n    // );\n\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(t.pages.proxies.title),\n        actions: [\n          PopupMenuButton<ProxiesSort>(\n            initialValue: sortBy,\n            onSelected: ref.read(proxiesSortNotifierProvider.notifier).update,\n            icon: const Icon(FluentIcons.arrow_sort_24_regular),\n            tooltip: t.pages.proxies.sort,\n            itemBuilder: (context) {\n              return [...ProxiesSort.values.map((e) => PopupMenuItem(value: e, child: Text(e.present(t))))];\n            },\n          ),\n          const Gap(8),\n        ],\n      ),\n      floatingActionButton: FloatingActionButton(\n        onPressed: () async => await ref.read(proxiesOverviewNotifierProvider.notifier).urlTest(\"select\"),\n        tooltip: t.pages.proxies.testDelay,\n        child: const Icon(FluentIcons.flash_24_filled),\n      ),\n      body: proxies.when(\n        data: (group) => group != null\n            ? LayoutBuilder(\n                builder: (context, constraints) {\n                  final width = constraints.maxWidth;\n                  final crossAxisCount = PlatformUtils.isMobile && width < 600 ? 1 : max(1, (width / 268).floor());\n                  return GridView.builder(\n                    padding: const EdgeInsets.only(bottom: 86),\n                    itemCount: group.items.length,\n                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(\n                      crossAxisCount: crossAxisCount,\n                      mainAxisExtent: 72,\n                    ),\n                    itemBuilder: (context, index) {\n                      final proxy = group.items[index];\n                      return ProxyTile(\n                        proxy,\n                        selected: group.selected == proxy.tag,\n                        onTap: () async {\n                          await ref.read(proxiesOverviewNotifierProvider.notifier).changeProxy(group.tag, proxy.tag);\n                          // if (selectActiveProxyMutation.state.isInProgress) return;\n                          // selectActiveProxyMutation.setFuture(\n                          // );\n                        },\n                      );\n                    },\n                  );\n                },\n              )\n            : Center(child: Text(t.pages.proxies.empty)),\n        error: (error, stackTrace) => Center(child: Text(t.presentShortError(error))),\n        loading: () => const Center(child: CircularProgressIndicator()),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/proxy/widget/proxy_tile.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/proxy/active/ip_widget.dart';\nimport 'package:hiddify/gen/fonts.gen.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hiddify/utils/platform_utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ProxyTile extends HookConsumerWidget with PresLogger {\n  const ProxyTile(this.proxy, {super.key, required this.selected, required this.onTap});\n\n  final OutboundInfo proxy;\n  final bool selected;\n  final GestureTapCallback? onTap;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final theme = Theme.of(context);\n\n    return ListTile(\n      // shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),\n      title: Text(\n        proxy.tagDisplay,\n        overflow: TextOverflow.ellipsis,\n        style: PlatformUtils.isWindows ? const TextStyle(fontFamily: FontFamily.emoji) : null,\n      ),\n      leading: IPCountryFlag(\n        countryCode: proxy.ipinfo.countryCode,\n        organization: proxy.ipinfo.org,\n        size: 40,\n        padding: const EdgeInsetsDirectional.only(end: 8),\n      ),\n      subtitle: Text.rich(\n        TextSpan(\n          text: proxy.type,\n          children: [\n            if (proxy.isGroup)\n              TextSpan(\n                text: ' (${proxy.groupSelectedTagDisplay.trim()})',\n                style: Theme.of(context).textTheme.bodySmall,\n              ),\n          ],\n        ),\n        maxLines: 1,\n        overflow: TextOverflow.ellipsis,\n      ),\n      trailing: Column(\n        children: [\n          if (proxy.urlTestDelay != 0)\n            Text(\n              proxy.urlTestDelay > 65000 ? \"×\" : proxy.urlTestDelay.toString(),\n              style: TextStyle(color: delayColor(context, proxy.urlTestDelay)),\n            ),\n\n          if (proxy.download > 0) Text(\"⬩\", style: Theme.of(context).textTheme.bodySmall),\n        ],\n      ),\n\n      selected: selected,\n      selectedTileColor: theme.colorScheme.primaryContainer,\n      onTap: onTap,\n      onLongPress: () async => await ref.read(dialogNotifierProvider.notifier).showProxyInfo(outboundInfo: proxy),\n      horizontalTitleGap: 4,\n    );\n  }\n\n  Color delayColor(BuildContext context, int delay) {\n    if (Theme.of(context).brightness == Brightness.dark) {\n      return switch (delay) {\n        < 800 => Colors.lightGreen,\n        < 1500 => Colors.orange,\n        _ => Colors.redAccent,\n      };\n    }\n    return switch (delay) {\n      < 800 => Colors.green,\n      < 1500 => Colors.deepOrangeAccent,\n      _ => Colors.red,\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/route_rules/notifier/android_apps_notifier.dart",
    "content": "// ignore: unused_import\r\nimport 'package:dio/dio.dart';\r\n// ignore: depend_on_referenced_packages\r\nimport 'package:flutter_riverpod/flutter_riverpod.dart';\r\nimport 'package:hiddify/features/route_rules/notifier/rule_notifier.dart';\r\nimport 'package:hiddify/utils/utils.dart';\r\nimport 'package:installed_apps/app_info.dart';\r\nimport 'package:installed_apps/installed_apps.dart';\r\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\r\n\r\npart 'android_apps_notifier.g.dart';\r\n\r\n@riverpod\r\nFuture<List<AppInfo>> apps(Ref ref) async {\r\n  if (!PlatformUtils.isAndroid) return [];\r\n  return await InstalledApps.getInstalledApps(false, true);\r\n}\r\n\r\n@riverpod\r\nFuture<List<AppInfo>> appsHideSystem(Ref ref) async {\r\n  if (!PlatformUtils.isAndroid) return [];\r\n  return await InstalledApps.getInstalledApps(true, true);\r\n}\r\n\r\n@riverpod\r\nFuture<List<String>> appPackages(Ref ref) async {\r\n  if (!PlatformUtils.isAndroid) return [];\r\n  return (await InstalledApps.getInstalledApps(false)).map((e) => e.packageName).toList();\r\n}\r\n\r\n@riverpod\r\nFuture<List<AppInfo>> filteredByHideSystem(Ref ref) async {\r\n  final hideSystem = ref.watch(hideSystemNotifierProvider);\r\n  return hideSystem ? await ref.watch(appsHideSystemProvider.future) : await ref.watch(appsProvider.future);\r\n}\r\n\r\n@riverpod\r\nFuture<List<String>> uninstalledPackages(Ref ref, int? ruleListOrder) async {\r\n  final allPackages = await ref.watch(appPackagesProvider.future);\r\n  final selectedPackages = ref.read(SelectedPackagesNotifierProvider(ruleListOrder));\r\n  return selectedPackages.toSet().difference(allPackages.toSet()).toList();\r\n}\r\n\r\n@riverpod\r\nFuture<List<dynamic>> filterBySearch(Ref ref, int? ruleListOrder) async {\r\n  final searchQuery = ref.watch(searchQueryNotifierProvider);\r\n  final filteredByHideSystem = await ref.watch(filteredByHideSystemProvider.future);\r\n\r\n  if (searchQuery.isEmpty) {\r\n    final selected = ref.read(SelectedPackagesNotifierProvider(ruleListOrder));\r\n    final uninstalledPackages = await ref.read(UninstalledPackagesProvider(ruleListOrder).future);\r\n    final fullList = [...uninstalledPackages, ...filteredByHideSystem];\r\n    fullList.sort((a, b) {\r\n      final aValue = (a is String) ? a : (a as AppInfo).packageName;\r\n      final bValue = (b is String) ? b : (b as AppInfo).packageName;\r\n\r\n      final aIndex = selected.indexOf(aValue);\r\n      final bIndex = selected.indexOf(bValue);\r\n\r\n      if (aIndex == -1 && bIndex == -1) return 0;\r\n      if (aIndex == -1) return 1;\r\n      if (bIndex == -1) return -1;\r\n\r\n      return aIndex.compareTo(bIndex);\r\n    });\r\n    return fullList;\r\n  } else {\r\n    return filteredByHideSystem.where((app) => app.name.toLowerCase().contains(searchQuery.toLowerCase())).toList();\r\n  }\r\n}\r\n\r\n@riverpod\r\nclass HideSystemNotifier extends _$HideSystemNotifier {\r\n  @override\r\n  bool build() {\r\n    return false;\r\n  }\r\n\r\n  void show() => state = false;\r\n\r\n  void hide() => state = true;\r\n}\r\n\r\n@riverpod\r\nclass SearchQueryNotifier extends _$SearchQueryNotifier {\r\n  @override\r\n  String build() => '';\r\n\r\n  void setQuery(String query) => state = query.trim();\r\n\r\n  void clear() => state = '';\r\n}\r\n\r\n@riverpod\r\nclass SelectedPackagesNotifier extends _$SelectedPackagesNotifier {\r\n  late int? _ruleListOrder;\r\n  final _ruleEnum = RuleEnum.packageName;\r\n\r\n  @override\r\n  List<String> build(int? ruleListOrder) {\r\n    _ruleListOrder = ruleListOrder;\r\n    final value = ref.read(ruleNotifierProvider(ruleListOrder)).writeToJsonMap()['${_ruleEnum.getIndex()}'];\r\n    if (value is List) return value.cast<String>();\r\n    return [];\r\n  }\r\n\r\n  void onChanged(String packageName) {\r\n    if (state.contains(packageName)) {\r\n      state = List.from(state)..removeWhere((element) => element == packageName);\r\n    } else {\r\n      state = [...state, packageName];\r\n    }\r\n    _save();\r\n  }\r\n\r\n  void clearSelection() {\r\n    state = [];\r\n    _save();\r\n  }\r\n\r\n  void _save() => ref.read(ruleNotifierProvider(_ruleListOrder).notifier).update<List<dynamic>>(_ruleEnum, state);\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/notifier/generic_list_notifier.dart",
    "content": "import 'package:hiddify/core/notification/in_app_notification_controller.dart';\r\nimport 'package:hiddify/features/route_rules/notifier/rule_notifier.dart';\r\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\r\n\r\npart 'generic_list_notifier.g.dart';\r\n\r\n@riverpod\r\nclass GenericListNotifier extends _$GenericListNotifier {\r\n  late int? _ruleListOrder;\r\n  late RuleEnum _ruleEnum;\r\n\r\n  @override\r\n  List<dynamic> build(int? ruleListOrder, RuleEnum ruleEnum) {\r\n    _ruleListOrder = ruleListOrder;\r\n    _ruleEnum = ruleEnum;\r\n    final value = ref.read(ruleNotifierProvider(ruleListOrder)).writeToJsonMap()['${ruleEnum.getIndex()}'];\r\n    if (value is List) return value;\r\n    return [];\r\n  }\r\n\r\n  void add(dynamic value) {\r\n    if (!_isValid(value)) return;\r\n    state = [...state, value];\r\n    _save();\r\n  }\r\n\r\n  void update(int index, dynamic value) {\r\n    if (!_isValid(value)) return;\r\n    state = List.from(state)..[index] = value;\r\n    _save();\r\n  }\r\n\r\n  void remove(int index) {\r\n    state = List.from(state)..removeAt(index);\r\n    _save();\r\n  }\r\n\r\n  void reset() {\r\n    state = [];\r\n    _save();\r\n  }\r\n\r\n  void _save() => ref.read(ruleNotifierProvider(_ruleListOrder).notifier).update<List<dynamic>>(_ruleEnum, state);\r\n\r\n  bool _isValid(dynamic value) {\r\n    if (value == null) return false;\r\n    if (state.contains(value)) {\r\n      ref.read(inAppNotificationControllerProvider).showErrorToast('Value is exist');\r\n      return false;\r\n    }\r\n    return true;\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/notifier/rule_notifier.dart",
    "content": "import 'dart:convert';\n\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/features/route_rules/notifier/rules_notifier.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/config/route_rule.pb.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:protobuf/protobuf.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'rule_notifier.g.dart';\n\nenum RuleEnum {\n  listOrder,\n  enabled,\n  name,\n  outbound,\n  ruleSet,\n  packageName,\n  processName,\n  processPath,\n  network,\n  portRange,\n  sourcePortRange,\n  protocol,\n  ipCidr,\n  sourceIpCidr,\n  domain,\n  domainSuffix,\n  domainKeyword,\n  domainRegex;\n\n  int getIndex() => index + 1;\n\n  String present(Translations t) => switch (this) {\n    listOrder => this.name,\n    enabled => this.name,\n    name => t.pages.settings.routing.routeRule.rule.tileTitle['name']!,\n    outbound => t.pages.settings.routing.routeRule.rule.tileTitle['outbound']!,\n    ruleSet => t.pages.settings.routing.routeRule.rule.tileTitle['rule_set']!,\n    packageName => t.pages.settings.routing.routeRule.rule.tileTitle['package_name']!,\n    processName => t.pages.settings.routing.routeRule.rule.tileTitle['process_name']!,\n    processPath => t.pages.settings.routing.routeRule.rule.tileTitle['process_path']!,\n    network => t.pages.settings.routing.routeRule.rule.tileTitle['network']!,\n    portRange => t.pages.settings.routing.routeRule.rule.tileTitle['port_range']!,\n    sourcePortRange => t.pages.settings.routing.routeRule.rule.tileTitle['source_port_range']!,\n    protocol => t.pages.settings.routing.routeRule.rule.tileTitle['protocol']!,\n    ipCidr => t.pages.settings.routing.routeRule.rule.tileTitle['ip_cidr']!,\n    sourceIpCidr => t.pages.settings.routing.routeRule.rule.tileTitle['source_ip_cidr']!,\n    domain => t.pages.settings.routing.routeRule.rule.tileTitle['domain']!,\n    domainSuffix => t.pages.settings.routing.routeRule.rule.tileTitle['domain_suffixe']!,\n    domainKeyword => t.pages.settings.routing.routeRule.rule.tileTitle['domain_keyword']!,\n    domainRegex => t.pages.settings.routing.routeRule.rule.tileTitle['domain_regex']!,\n  };\n}\n\n@riverpod\nclass RuleNotifier extends _$RuleNotifier {\n  bool isEditMode = false;\n\n  @override\n  Rule build(int? listOrder) {\n    if (listOrder == null) {\n      return Rule(name: 'Rule Name', outbound: Outbound.direct, network: Network.all);\n    } else {\n      isEditMode = true;\n      return ref.read(rulesNotifierProvider).where((rule) => rule.listOrder == listOrder).first;\n    }\n  }\n\n  void update<T>(RuleEnum key, T value) {\n    final map = state.writeToJsonMap();\n    map['${key.getIndex()}'] = value is ProtobufEnum\n        ? '${value.value}'\n        : value is List<ProtobufEnum>\n        ? value.map((e) => '${e.value}').toList()\n        : value;\n    state = Rule.fromJson(jsonEncode(map));\n  }\n\n  void save() {\n    assert(state.hasName() && state.hasOutbound());\n    if (isEditMode) {\n      assert(state.hasListOrder() && state.hasEnabled());\n      ref.read(rulesNotifierProvider.notifier).updateRule(state);\n    } else {\n      ref.read(rulesNotifierProvider.notifier).addRule(state);\n    }\n  }\n}\n\n@riverpod\nbool isRuleEdited(Ref ref, int? listOrder) {\n  if (listOrder == null) return true;\n  return ref.watch(RuleNotifierProvider(listOrder)) !=\n      ref.watch(rulesNotifierProvider.select((value) => value.where((rule) => rule.listOrder == listOrder))).first;\n}\n\n@riverpod\nclass DialogCheckboxNotifier extends _$DialogCheckboxNotifier {\n  @override\n  List<ProtobufEnum> build(List<ProtobufEnum> selected) {\n    return selected;\n  }\n\n  void update(ProtobufEnum value) {\n    state = state.contains(value) ? state.where((element) => element != value).toList() : [...state, value];\n  }\n}\n"
  },
  {
    "path": "lib/features/route_rules/notifier/rules_notifier.dart",
    "content": "import 'dart:convert';\nimport 'dart:io';\n\nimport 'package:dartx/dartx_io.dart';\nimport 'package:file_picker/file_picker.dart';\nimport 'package:flutter/services.dart';\nimport 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/config/route_rule.pb.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'rules_notifier.g.dart';\n\n@riverpod\nclass RulesNotifier extends _$RulesNotifier with AppLogger {\n  late File file;\n\n  @override\n  List<Rule> build() {\n    final directories = ref.watch(appDirectoriesProvider).requireValue;\n    file = File('${directories.baseDir.path}/route_rule.proto');\n    if (file.existsSync()) {\n      return RouteRule.fromBuffer(file.readAsBytesSync()).rules;\n    } else {\n      return <Rule>[];\n    }\n  }\n\n  Future<void> addRule(Rule rule) async {\n    final current = state;\n    assert(rule.hasName() && rule.hasOutbound());\n    rule\n      ..listOrder = current.length\n      ..enabled = true;\n    state = [...current, rule];\n    await _updateFile();\n  }\n\n  Future<void> updateRule(Rule rule) async {\n    final current = state;\n    final index = current.indexWhere((element) => element.listOrder == rule.listOrder);\n    if (index == -1) return;\n    current[index] = rule;\n    state = current.toList();\n    await _updateFile();\n  }\n\n  Future<void> deleteRule(int listOrder) async {\n    final current = state;\n    state = _updateListOrder(current.where((element) => element.listOrder != listOrder).toList());\n    await _updateFile();\n  }\n\n  Future<void> reorder(int oldIndex, int newIndex) async {\n    final current = state;\n    final rule = current.removeAt(oldIndex);\n    current.insert(oldIndex < newIndex ? newIndex - 1 : newIndex, rule);\n    state = _updateListOrder(current).toList();\n    await _updateFile();\n  }\n\n  Future<void> updateEnabled(bool enabled, int listOrder) async {\n    final current = state;\n    current.firstWhere((rule) => rule.listOrder == listOrder).enabled = enabled;\n    state = current.toList();\n    await _updateFile();\n  }\n\n  //export Clipboard\n  Future<bool> exportJsonToClipboard() async {\n    final t = ref.read(translationsProvider).requireValue;\n    try {\n      final routeRules = RouteRule(rules: state);\n      await Clipboard.setData(ClipboardData(text: jsonEncode(routeRules.writeToJson())));\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.export.clipboard.success);\n      return true;\n    } on PlatformException {\n      ref\n          .read(inAppNotificationControllerProvider)\n          .showInfoToast(t.common.msg.export.clipboard.contentTooLarge, duration: const Duration(seconds: 5));\n      return false;\n    } catch (e, st) {\n      loggy.warning(\"error exporting route rules to clipboard\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.export.clipboard.failure);\n      return false;\n    }\n  }\n\n  //import Clipboard\n  Future<bool> importRulesFromClipboard() async {\n    final t = ref.read(translationsProvider).requireValue;\n    try {\n      final input = await Clipboard.getData(Clipboard.kTextPlain).then((value) => value?.text);\n      if (input == null) return false;\n      final routeRules = RouteRule.fromJson(jsonDecode(input) as String);\n      state = routeRules.rules;\n      await _updateFile();\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.import.success);\n      return true;\n    } catch (e, st) {\n      loggy.warning(\"error importing route rules from clipboard\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.import.failure);\n      return false;\n    }\n  }\n\n  //export JSON\n  Future<bool> saveRulesAsJsonFile() async {\n    final t = ref.read(translationsProvider).requireValue;\n    try {\n      final bytes = utf8.encode(RouteRule(rules: state).writeToJson());\n      final outputFile = await FilePicker.platform.saveFile(\n        fileName: 'route_rules.json',\n        type: FileType.custom,\n        allowedExtensions: ['json'],\n        bytes: bytes,\n      );\n      if (outputFile == null) return false;\n      if (PlatformUtils.isDesktop) {\n        final file = File(outputFile);\n        if (file.extension != '.json') return false;\n        if (!await file.exists()) await file.parent.create(recursive: true);\n        await file.writeAsBytes(bytes);\n      }\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.export.file.success);\n      return true;\n    } catch (e, st) {\n      loggy.warning(\"error exporting route rules to json file\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.export.file.failure);\n      return false;\n    }\n  }\n\n  //import JSON\n  Future<bool> importRulesFromJsonFile() async {\n    final t = ref.read(translationsProvider).requireValue;\n    try {\n      final result = await FilePicker.platform.pickFiles(type: FileType.custom, allowedExtensions: ['json']);\n      if (result == null) return false;\n      final file = File(result.files.single.path!);\n      if (!await file.exists()) return false;\n      final bytes = await file.readAsBytes();\n      final routeRules = RouteRule.fromJson(utf8.decode(bytes));\n      state = routeRules.rules;\n      await _updateFile();\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.import.success);\n      return true;\n    } catch (e, st) {\n      loggy.warning(\"error importing route rules from json file\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.import.failure);\n      return false;\n    }\n  }\n\n  Future<void> resetRules() async {\n    if (await file.exists()) {\n      await file.delete(recursive: true);\n      state = <Rule>[];\n    }\n  }\n\n  Future<void> _updateFile() async {\n    if (!await file.exists()) {\n      await file.parent.create(recursive: true);\n    }\n    final sortedRules = state..sort((a, b) => a.listOrder.compareTo(b.listOrder));\n    final routeRules = RouteRule(rules: sortedRules);\n    await file.writeAsBytes(routeRules.writeToBuffer());\n  }\n\n  List<Rule> _updateListOrder(List<Rule> rules) {\n    for (var i = 0; i < rules.length; i++) {\n      rules[i].listOrder = i;\n    }\n    return rules;\n  }\n}\n"
  },
  {
    "path": "lib/features/route_rules/overview/android_apps_page.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:flutter_hooks/flutter_hooks.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/features/route_rules/notifier/android_apps_notifier.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\nimport 'package:installed_apps/app_info.dart';\r\n\r\nclass AndroidAppsPage extends HookConsumerWidget {\r\n  const AndroidAppsPage({super.key, this.ruleListOrder});\r\n\r\n  final int? ruleListOrder;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    final theme = Theme.of(context);\r\n    final searchController = useTextEditingController();\r\n    ref.listen(searchQueryNotifierProvider, (_, next) => searchController.text = next);\r\n    final focusNode = useFocusNode();\r\n    ref.watch(appPackagesProvider);\r\n    final selectedNotifier = SelectedPackagesNotifierProvider(ruleListOrder);\r\n    final selected = ref.watch(selectedNotifier);\r\n    final combinedList = ref.watch(FilterBySearchProvider(ruleListOrder));\r\n\r\n    final menuItems = <PopupMenuItem>[\r\n      if (ref.watch(hideSystemNotifierProvider))\r\n        PopupMenuItem(\r\n          onTap: ref.read(hideSystemNotifierProvider.notifier).show,\r\n          child: Text(t.pages.settings.routing.routeRule.androidApps.showSystemApps),\r\n        )\r\n      else\r\n        PopupMenuItem(\r\n          onTap: ref.read(hideSystemNotifierProvider.notifier).hide,\r\n          child: Text(t.pages.settings.routing.routeRule.androidApps.hideSystemApps),\r\n        ),\r\n      PopupMenuItem(\r\n        onTap: ref.read(selectedNotifier.notifier).clearSelection,\r\n        child: Text(t.pages.settings.routing.routeRule.androidApps.clearSelection),\r\n      ),\r\n    ];\r\n\r\n    return Scaffold(\r\n      appBar: AppBar(\r\n        title: Text(t.pages.settings.routing.routeRule.androidApps.pageTitle),\r\n        actions: [\r\n          PopupMenuButton(\r\n            icon: const Icon(Icons.more_vert_rounded),\r\n            itemBuilder: (_) => selected.isEmpty ? [menuItems.first] : menuItems,\r\n          ),\r\n        ],\r\n        bottom: PreferredSize(\r\n          preferredSize: const Size.fromHeight(kMinInteractiveDimension),\r\n          child: TextField(\r\n            focusNode: focusNode,\r\n            controller: searchController,\r\n            decoration: InputDecoration(\r\n              contentPadding: const EdgeInsets.symmetric(horizontal: 16),\r\n              label: Text(t.common.search),\r\n              suffixIcon: searchController.text.isNotEmpty\r\n                  ? IconButton(\r\n                      onPressed: () {\r\n                        ref.read(searchQueryNotifierProvider.notifier).clear();\r\n                        focusNode.unfocus();\r\n                      },\r\n                      icon: const Icon(Icons.cancel_outlined),\r\n                    )\r\n                  : null,\r\n            ),\r\n            onChanged: (value) => ref.read(searchQueryNotifierProvider.notifier).setQuery(value),\r\n          ),\r\n        ),\r\n      ),\r\n      body: combinedList.when(\r\n        data: (items) => ListView.builder(\r\n          itemCount: items.length,\r\n          itemBuilder: (context, index) {\r\n            final item = items[index];\r\n            if (item is AppInfo) {\r\n              final appInfo = item;\r\n              return CheckboxListTile(\r\n                title: Row(\r\n                  children: [\r\n                    SizedBox(\r\n                      width: 40,\r\n                      height: 40,\r\n                      child: CircleAvatar(backgroundColor: Colors.transparent, child: Image.memory(appInfo.icon!)),\r\n                    ),\r\n                    const Gap(16),\r\n                    Expanded(\r\n                      child: Column(\r\n                        crossAxisAlignment: CrossAxisAlignment.start,\r\n                        children: [\r\n                          Text(appInfo.name, style: theme.textTheme.bodyLarge, overflow: TextOverflow.ellipsis),\r\n                          Text(appInfo.packageName, style: theme.textTheme.bodySmall, overflow: TextOverflow.ellipsis),\r\n                        ],\r\n                      ),\r\n                    ),\r\n                  ],\r\n                ),\r\n                value: selected.contains(item.packageName),\r\n                onChanged: (_) => ref.read(selectedNotifier.notifier).onChanged(item.packageName),\r\n              );\r\n            } else if (item is String) {\r\n              final packageName = item;\r\n              return CheckboxListTile(\r\n                title: Column(\r\n                  crossAxisAlignment: CrossAxisAlignment.start,\r\n                  children: [\r\n                    Row(\r\n                      children: [\r\n                        const Icon(size: 16, Icons.warning_rounded, color: Colors.amber),\r\n                        const Gap(4),\r\n                        Text(\r\n                          t.pages.settings.routing.routeRule.androidApps.uninstalled,\r\n                          style: theme.textTheme.bodyLarge,\r\n                          overflow: TextOverflow.ellipsis,\r\n                        ),\r\n                      ],\r\n                    ),\r\n                    Text(packageName, style: theme.textTheme.bodySmall, overflow: TextOverflow.ellipsis),\r\n                  ],\r\n                ),\r\n                value: selected.contains(packageName),\r\n                onChanged: (_) => ref.read(selectedNotifier.notifier).onChanged(packageName),\r\n              );\r\n            } else {\r\n              throw Exception('Data type is not supported');\r\n            }\r\n          },\r\n        ),\r\n        loading: () => const Center(child: CircularProgressIndicator()),\r\n        error: (error, stack) => Center(child: Text('Error: $error')),\r\n      ),\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/overview/generic_list_page.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\r\nimport 'package:hiddify/features/route_rules/notifier/generic_list_notifier.dart';\r\nimport 'package:hiddify/features/route_rules/notifier/rule_notifier.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\nimport 'package:text_scroll/text_scroll.dart';\r\n\r\nclass GenericListPage extends HookConsumerWidget {\r\n  const GenericListPage({super.key, this.ruleListOrder, required this.ruleEnum, this.validator});\r\n\r\n  final int? ruleListOrder;\r\n  final RuleEnum ruleEnum;\r\n  final FormFieldValidator<String>? validator;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    final provider = genericListNotifierProvider(ruleListOrder, ruleEnum);\r\n    final list = ref.watch(provider);\r\n\r\n    Future<void> addNewValue() async {\r\n      final result = await ref\r\n          .read(dialogNotifierProvider.notifier)\r\n          .showSettingText(lable: t.pages.settings.routing.routeRule.genericList.addNew, validator: validator);\r\n      if (result is String) ref.read(provider.notifier).add(result);\r\n    }\r\n\r\n    return Scaffold(\r\n      appBar: AppBar(\r\n        title: Text(ruleEnum.present(t)),\r\n        actions: [\r\n          IconButton(\r\n            onPressed: list.isEmpty\r\n                ? null\r\n                : () async {\r\n                    final result = await ref\r\n                        .read(dialogNotifierProvider.notifier)\r\n                        .showConfirmation(\r\n                          title: t.pages.settings.routing.routeRule.genericList.clearList,\r\n                          message: t.pages.settings.routing.routeRule.genericList.clearListMsg,\r\n                        );\r\n                    if (result == true) ref.read(provider.notifier).reset();\r\n                  },\r\n            icon: const Icon(Icons.clear_all),\r\n          ),\r\n          const Gap(8),\r\n        ],\r\n      ),\r\n      floatingActionButton: list.isNotEmpty\r\n          ? FloatingActionButton(onPressed: addNewValue, child: const Icon(Icons.add_rounded))\r\n          : FloatingActionButton.extended(\r\n              onPressed: addNewValue,\r\n              label: Text(t.pages.settings.routing.routeRule.genericList.addNew),\r\n              icon: const Icon(Icons.add_rounded),\r\n            ),\r\n      body: ListView.builder(\r\n        itemBuilder: (context, index) => GenericListTile(\r\n          value: list[index],\r\n          onRemove: () => ref.read(provider.notifier).remove(index),\r\n          onUpdate: () async {\r\n            final result = await ref\r\n                .read(dialogNotifierProvider.notifier)\r\n                .showSettingText(\r\n                  lable: t.pages.settings.routing.routeRule.genericList.update,\r\n                  value: '${list[index]}',\r\n                  validator: validator,\r\n                );\r\n            if (result is String) ref.read(provider.notifier).update(index, result);\r\n          },\r\n        ),\r\n        itemCount: list.length,\r\n      ),\r\n    );\r\n  }\r\n}\r\n\r\nclass GenericListTile extends ConsumerWidget {\r\n  const GenericListTile({super.key, required this.value, required this.onRemove, required this.onUpdate});\r\n\r\n  final dynamic value;\r\n  final VoidCallback? onRemove;\r\n  final VoidCallback? onUpdate;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    return ListTile(\r\n      onTap: onUpdate,\r\n      title: TextScroll(\r\n        '$value',\r\n        mode: TextScrollMode.bouncing,\r\n        velocity: const Velocity(pixelsPerSecond: Offset(30, 0)),\r\n        pauseOnBounce: const Duration(seconds: 2),\r\n        pauseBetween: const Duration(seconds: 2),\r\n      ),\r\n      trailing: IconButton(onPressed: onRemove, icon: const Icon(Icons.remove)),\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/overview/rule_page.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\r\nimport 'package:hiddify/features/route_rules/notifier/rule_notifier.dart';\r\nimport 'package:hiddify/features/route_rules/overview/android_apps_page.dart';\r\nimport 'package:hiddify/features/route_rules/overview/generic_list_page.dart';\r\nimport 'package:hiddify/features/route_rules/widget/setting_checkbox.dart';\r\nimport 'package:hiddify/features/route_rules/widget/setting_divider.dart';\r\nimport 'package:hiddify/features/route_rules/widget/setting_generic_list.dart';\r\nimport 'package:hiddify/features/route_rules/widget/setting_radio.dart';\r\nimport 'package:hiddify/features/route_rules/widget/setting_text.dart';\r\nimport 'package:hiddify/hiddifycore/generated/v2/config/route_rule.pb.dart';\r\nimport 'package:hiddify/utils/utils.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\nimport 'package:protobuf/protobuf.dart';\r\nimport 'package:recase/recase.dart';\r\n\r\nclass RulePage extends HookConsumerWidget {\r\n  const RulePage({super.key, this.ruleListOrder});\r\n\r\n  final int? ruleListOrder;\r\n\r\n  String getTitle(Map<String, String> t, RuleEnum key) => t[key.name.snakeCase] ?? key.name;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    final isRuleEdited = ref.watch(IsRuleEditedProvider(ruleListOrder));\r\n    // TODO(): PopScope logic must be transferred to onExit method of go_router\r\n    return PopScope(\r\n      canPop: !isRuleEdited,\r\n      onPopInvokedWithResult: (didPop, result) async {\r\n        if (didPop) return;\r\n        if (isRuleEdited) {\r\n          final shouldSave = await ref\r\n              .read(dialogNotifierProvider.notifier)\r\n              .showSave(\r\n                title: t.pages.settings.routing.routeRule.rule.ruleChanged,\r\n                description: t.pages.settings.routing.routeRule.rule.ruleChangedMsg,\r\n              );\r\n          if (shouldSave == null) return;\r\n          if (shouldSave == true) {\r\n            ref.read(ruleNotifierProvider(ruleListOrder).notifier).save();\r\n            if (context.mounted) Navigator.of(context).pop();\r\n          } else {\r\n            if (context.mounted) Navigator.of(context).pop();\r\n          }\r\n        }\r\n      },\r\n      child: Scaffold(\r\n        appBar: AppBar(\r\n          title: Text(t.pages.settings.routing.routeRule.rule.title),\r\n          actions: [\r\n            IconButton(\r\n              onPressed: isRuleEdited\r\n                  ? () {\r\n                      ref.read(ruleNotifierProvider(ruleListOrder).notifier).save();\r\n                      Navigator.of(context).pop();\r\n                    }\r\n                  : null,\r\n              icon: const Icon(Icons.check),\r\n            ),\r\n            const Gap(8),\r\n          ],\r\n        ),\r\n        body: SingleChildScrollView(\r\n          child: Column(\r\n            children: [\r\n              SettingText(\r\n                title: RuleEnum.name.present(t),\r\n                value: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.name)),\r\n                setValue: (value) =>\r\n                    ref.read(ruleNotifierProvider(ruleListOrder).notifier).update<String>(RuleEnum.name, value),\r\n              ),\r\n              SettingRadio<Outbound>(\r\n                title: RuleEnum.outbound.present(t),\r\n                values: Outbound.values,\r\n                value: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.outbound)),\r\n                setValue: (value) =>\r\n                    ref.read(ruleNotifierProvider(ruleListOrder).notifier).update<Outbound>(RuleEnum.outbound, value),\r\n                defaultValue: Outbound.direct,\r\n                t: t.pages.settings.routing.routeRule.rule.outbound,\r\n              ),\r\n              const SettingDivider(),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.ruleSet.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.ruleSets)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => GenericListPage(\r\n                      ruleListOrder: ruleListOrder,\r\n                      ruleEnum: RuleEnum.ruleSet,\r\n                      validator: (value) {\r\n                        if (isUrl('$value')) return null;\r\n                        return t.pages.settings.routing.routeRule.rule.validUrl;\r\n                      },\r\n                    ),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n                useEllipsis: true,\r\n              ),\r\n              SettingDivider(title: t.pages.settings.routing.routeRule.rule.onlyTunMode),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.packageName.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.packageNames)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => AndroidAppsPage(ruleListOrder: ruleListOrder),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n                isPackageName: true,\r\n                showPlatformWarning: !PlatformUtils.isAndroid,\r\n              ),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.processName.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.processNames)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => GenericListPage(\r\n                      ruleListOrder: ruleListOrder,\r\n                      ruleEnum: RuleEnum.processName,\r\n                      validator: (value) {\r\n                        if (isProcessName('$value')) return null;\r\n                        return t.pages.settings.routing.routeRule.rule.validProcessName;\r\n                      },\r\n                    ),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n                showPlatformWarning: !PlatformUtils.isDesktop,\r\n              ),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.processPath.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.processPaths)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => GenericListPage(\r\n                      ruleListOrder: ruleListOrder,\r\n                      ruleEnum: RuleEnum.processPath,\r\n                      validator: (value) {\r\n                        if (isProcessPath('$value')) return null;\r\n                        return t.pages.settings.routing.routeRule.rule.validProcessPath;\r\n                      },\r\n                    ),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n                showPlatformWarning: !PlatformUtils.isDesktop,\r\n              ),\r\n              const SettingDivider(),\r\n              SettingRadio<Network>(\r\n                title: RuleEnum.network.present(t),\r\n                values: Network.values,\r\n                value: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.network)),\r\n                setValue: (value) =>\r\n                    ref.read(ruleNotifierProvider(ruleListOrder).notifier).update<Network>(RuleEnum.network, value),\r\n                defaultValue: Network.all,\r\n                t: t.pages.settings.routing.routeRule.rule.network,\r\n              ),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.portRange.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.portRanges)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => GenericListPage(\r\n                      ruleListOrder: ruleListOrder,\r\n                      ruleEnum: RuleEnum.portRange,\r\n                      validator: (value) {\r\n                        if (isPortOrPortRange('$value')) return null;\r\n                        return t.pages.settings.routing.routeRule.rule.validPortRange;\r\n                      },\r\n                    ),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n              ),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.sourcePortRange.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.sourcePortRanges)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => GenericListPage(\r\n                      ruleListOrder: ruleListOrder,\r\n                      ruleEnum: RuleEnum.sourcePortRange,\r\n                      validator: (value) {\r\n                        if (isPortOrPortRange('$value')) return null;\r\n                        return t.pages.settings.routing.routeRule.rule.validPortRange;\r\n                      },\r\n                    ),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n              ),\r\n              SettingCheckbox(\r\n                title: RuleEnum.protocol.present(t),\r\n                values: Protocol.values,\r\n                selectedValues: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.protocols)),\r\n                setValue: (value) => ref\r\n                    .read(ruleNotifierProvider(ruleListOrder).notifier)\r\n                    .update<List<ProtobufEnum>>(RuleEnum.protocol, value),\r\n                t: t.pages.settings.routing.routeRule.rule.protocol,\r\n              ),\r\n              const SettingDivider(),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.ipCidr.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.ipCidrs)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => GenericListPage(\r\n                      ruleListOrder: ruleListOrder,\r\n                      ruleEnum: RuleEnum.ipCidr,\r\n                      validator: (value) {\r\n                        if (isIpCidr('$value')) return null;\r\n                        return t.pages.settings.routing.routeRule.rule.validIpCidr;\r\n                      },\r\n                    ),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n              ),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.sourceIpCidr.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.sourceIpCidrs)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => GenericListPage(\r\n                      ruleListOrder: ruleListOrder,\r\n                      ruleEnum: RuleEnum.sourceIpCidr,\r\n                      validator: (value) {\r\n                        if (isIpCidr('$value')) return null;\r\n                        return t.pages.settings.routing.routeRule.rule.validIpCidr;\r\n                      },\r\n                    ),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n              ),\r\n              const SettingDivider(),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.domain.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.domains)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => GenericListPage(\r\n                      ruleListOrder: ruleListOrder,\r\n                      ruleEnum: RuleEnum.domain,\r\n                      validator: (value) {\r\n                        if (isDomain('$value')) return null;\r\n                        return t.pages.settings.routing.routeRule.rule.validDomain;\r\n                      },\r\n                    ),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n              ),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.domainSuffix.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.domainSuffixes)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => GenericListPage(\r\n                      ruleListOrder: ruleListOrder,\r\n                      ruleEnum: RuleEnum.domainSuffix,\r\n                      validator: (value) {\r\n                        if (isDomainSuffix('$value')) return null;\r\n                        return t.pages.settings.routing.routeRule.rule.validDomainSuffix;\r\n                      },\r\n                    ),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n              ),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.domainKeyword.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.domainKeywords)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) =>\r\n                        GenericListPage(ruleListOrder: ruleListOrder, ruleEnum: RuleEnum.domainKeyword),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n              ),\r\n              SettingGenericList<String>(\r\n                title: RuleEnum.domainRegex.present(t),\r\n                values: ref.watch(ruleNotifierProvider(ruleListOrder).select((value) => value.domainRegexes)),\r\n                onTap: () => Navigator.of(context).push(\r\n                  MaterialPageRoute(\r\n                    builder: (context) => GenericListPage(ruleListOrder: ruleListOrder, ruleEnum: RuleEnum.domainRegex),\r\n                    fullscreenDialog: true,\r\n                  ),\r\n                ),\r\n              ),\r\n            ],\r\n          ),\r\n        ),\r\n      ),\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/overview/rules_page.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/features/route_rules/notifier/rules_notifier.dart';\nimport 'package:hiddify/features/route_rules/overview/rule_page.dart';\nimport 'package:hiddify/features/route_rules/widget/rule_tile.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass RulesPage extends HookConsumerWidget {\n  const RulesPage({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final rules = ref.watch(rulesNotifierProvider);\n    final menuItems = <PopupMenuEntry>[\n      PopupMenuItem(\n        onTap: ref.read(rulesNotifierProvider.notifier).importRulesFromClipboard,\n        child: Text(t.pages.settings.routing.routeRule.options.import.clipboard),\n      ),\n      PopupMenuItem(\n        onTap: ref.read(rulesNotifierProvider.notifier).importRulesFromJsonFile,\n        child: Text(t.pages.settings.routing.routeRule.options.import.file),\n      ),\n      const PopupMenuDivider(),\n      PopupMenuItem(\n        onTap: () async => await ref.read(rulesNotifierProvider.notifier).exportJsonToClipboard(),\n        child: Text(t.pages.settings.routing.routeRule.options.export.clipboard),\n      ),\n      PopupMenuItem(\n        onTap: () async => await ref.read(rulesNotifierProvider.notifier).saveRulesAsJsonFile(),\n        child: Text(t.pages.settings.routing.routeRule.options.export.file),\n      ),\n      const PopupMenuDivider(),\n      PopupMenuItem(\n        onTap: ref.read(rulesNotifierProvider.notifier).resetRules,\n        child: Text(t.pages.settings.routing.routeRule.options.reset),\n      ),\n    ];\n\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(t.pages.settings.routing.routeRule.title),\n        actions: [\n          PopupMenuButton(\n            icon: const Icon(Icons.more_vert_rounded),\n            itemBuilder: (_) => rules.isEmpty ? menuItems.getRange(0, 2).toList() : menuItems,\n          ),\n          const Gap(8),\n        ],\n      ),\n      floatingActionButton: rules.isNotEmpty\n          ? FloatingActionButton(\n              onPressed: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => const RulePage())),\n              child: const Icon(Icons.add_rounded),\n            )\n          : FloatingActionButton.extended(\n              onPressed: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => const RulePage())),\n              label: Text(t.pages.settings.routing.routeRule.createRule),\n              icon: const Icon(Icons.add_rounded),\n            ),\n      body: ReorderableListView.builder(\n        buildDefaultDragHandles: false,\n        onReorder: ref.read(rulesNotifierProvider.notifier).reorder,\n        itemBuilder: (context, index) => RuleTile(key: Key('$index'), index: index, rule: rules[index]),\n        itemCount: rules.length,\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/route_rules/widget/rule_tile.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:flutter_hooks/flutter_hooks.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\r\nimport 'package:hiddify/features/route_rules/notifier/rules_notifier.dart';\r\nimport 'package:hiddify/features/route_rules/overview/rule_page.dart';\r\nimport 'package:hiddify/features/route_rules/widget/setting_detail_chips.dart';\r\nimport 'package:hiddify/hiddifycore/generated/v2/config/route_rule.pb.dart';\r\nimport 'package:hiddify/utils/platform_utils.dart';\r\n\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\nimport 'package:protobuf/protobuf.dart';\r\n\r\nclass RuleTile extends HookConsumerWidget {\r\n  const RuleTile({super.key, required this.index, required this.rule});\r\n\r\n  final Rule rule;\r\n  final int index;\r\n\r\n  Map detailChipsValue() {\r\n    final map = rule.toProto3Json()! as Map<String, dynamic>;\r\n    map.removeWhere((key, value) => ['list_order', 'enabled', 'name', 'outbound'].contains(key));\r\n    map.updateAll(\r\n      (key, value) => value is List\r\n          ? value.length\r\n          : value is ProtobufEnum\r\n          ? value.name\r\n          : value,\r\n    );\r\n    return map;\r\n  }\r\n\r\n  Map<String, String> mergeTranslation(List<Map<String, String>> translations) {\r\n    return Map.fromEntries(translations.expand((map) => map.entries).toList());\r\n  }\r\n\r\n  Future handleDelete(BuildContext context, WidgetRef ref) async {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    final result = await ref\r\n        .read(dialogNotifierProvider.notifier)\r\n        .showConfirmation(\r\n          title: t.dialogs.confirmation.routeRule.delete.title,\r\n          message: t.dialogs.confirmation.routeRule.delete.msg(rulename: rule.name),\r\n          positiveBtnTxt: t.common.delete,\r\n        );\r\n    if (result == true) {\r\n      await ref.read(rulesNotifierProvider.notifier).deleteRule(rule.listOrder);\r\n    }\r\n  }\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    final scrollController = useScrollController();\r\n    ref.listen(rulesNotifierProvider, (_, _) {\r\n      if (scrollController.offset > 0) scrollController.jumpTo(0);\r\n    });\r\n    return Material(\r\n      child: InkWell(\r\n        onTap: () => Navigator.of(\r\n          context,\r\n        ).push(MaterialPageRoute(builder: (context) => RulePage(ruleListOrder: rule.listOrder))),\r\n        onLongPress: () async => await handleDelete(context, ref),\r\n        onSecondaryTapUp: PlatformUtils.isDesktop\r\n            ? (details) {\r\n                final offset = details.globalPosition;\r\n                showMenu(\r\n                  context: context,\r\n                  position: RelativeRect.fromLTRB(offset.dx, offset.dy, offset.dx, offset.dy),\r\n                  items: [\r\n                    PopupMenuItem(\r\n                      child: Text(t.pages.settings.routing.routeRule.deleteRule),\r\n                      onTap: () async => await handleDelete(context, ref),\r\n                    ),\r\n                  ],\r\n                );\r\n              }\r\n            : null,\r\n        child: Column(\r\n          crossAxisAlignment: CrossAxisAlignment.start,\r\n          children: [\r\n            ListTile(\r\n              title: Text(\r\n                t.pages.settings.routing.routeRule.rule.outbound[rule.outbound.name] ?? rule.outbound.name,\r\n                style: Theme.of(context).textTheme.labelMedium,\r\n              ),\r\n              subtitle: Text(rule.name, style: Theme.of(context).textTheme.bodyLarge),\r\n              leading: ReorderableDragStartListener(index: index, child: const Icon(Icons.drag_handle_rounded)),\r\n              trailing: Switch(\r\n                value: rule.enabled,\r\n                onChanged: (value) async =>\r\n                    await ref.read(rulesNotifierProvider.notifier).updateEnabled(value, rule.listOrder),\r\n              ),\r\n            ),\r\n            SettingDetailChips<MapEntry>(\r\n              values: detailChipsValue().entries.toList(),\r\n              scrollController: scrollController,\r\n              t: mergeTranslation([\r\n                t.pages.settings.routing.routeRule.rule.tileTitle,\r\n                t.pages.settings.routing.routeRule.rule.network,\r\n                t.pages.settings.routing.routeRule.rule.outbound,\r\n              ]),\r\n            ),\r\n          ],\r\n        ),\r\n      ),\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/widget/setting_checkbox.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\nimport 'package:protobuf/protobuf.dart';\r\n\r\nclass SettingCheckbox extends ConsumerWidget {\r\n  const SettingCheckbox({\r\n    super.key,\r\n    required this.title,\r\n    required this.values,\r\n    required this.selectedValues,\r\n    required this.setValue,\r\n    this.defaultValue,\r\n    this.t,\r\n  });\r\n\r\n  final String title;\r\n  final List<ProtobufEnum> values;\r\n  final List<ProtobufEnum> selectedValues;\r\n  final Function(List<ProtobufEnum> value) setValue;\r\n  final List<ProtobufEnum>? defaultValue;\r\n  final Map<String, String>? t;\r\n\r\n  String textWithTranslation(List<ProtobufEnum> e, WidgetRef ref) {\r\n    if (t == null) {\r\n      return e.map((e) => '$e').toList().join(', ');\r\n    } else {\r\n      if (e.isEmpty) return t![''] ?? ref.watch(translationsProvider).requireValue.common.empty;\r\n      return e.map((e) => t!['$e'] ?? '$e').toList().join(', ');\r\n    }\r\n  }\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    return ListTile(\r\n      title: Text(title),\r\n      subtitle: Text(textWithTranslation(selectedValues, ref)),\r\n      onTap: () async {\r\n        final result = await ref\r\n            .read(dialogNotifierProvider.notifier)\r\n            .showSettingCheckbox(\r\n              title: title,\r\n              values: values,\r\n              selectedValues: selectedValues,\r\n              defaultValue: defaultValue,\r\n              t: t,\r\n            );\r\n        if (result is List<ProtobufEnum>) setValue(result);\r\n      },\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/widget/setting_detail_chips.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:flutter_hooks/flutter_hooks.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hiddify/utils/platform_utils.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\nimport 'package:installed_apps/app_info.dart';\r\nimport 'package:installed_apps/installed_apps.dart';\r\n\r\nclass SettingDetailChips<T extends Object> extends HookConsumerWidget {\r\n  const SettingDetailChips({\r\n    super.key,\r\n    required this.values,\r\n    this.t,\r\n    this.scrollController,\r\n    this.useEllipsis = false,\r\n    this.isPackageName = false,\r\n  });\r\n\r\n  final List<T> values;\r\n  final Map<String, String>? t;\r\n  final ScrollController? scrollController;\r\n  final bool useEllipsis;\r\n  final bool isPackageName;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final controller = scrollController ?? useScrollController();\r\n    final showStartBtn = useState(false);\r\n    final showEndBtn = useState(true);\r\n\r\n    useEffect(() {\r\n      void listener() {\r\n        showStartBtn.value = controller.position.pixels > controller.position.minScrollExtent;\r\n        showEndBtn.value = controller.position.pixels < controller.position.maxScrollExtent;\r\n      }\r\n\r\n      controller.addListener(listener);\r\n      return () => controller.removeListener(listener);\r\n    }, [controller]);\r\n\r\n    void scrollToEnd() {\r\n      controller.animateTo(\r\n        controller.offset + 150,\r\n        duration: const Duration(milliseconds: 500),\r\n        curve: Curves.easeInOut,\r\n      );\r\n    }\r\n\r\n    void scrollToStart() {\r\n      controller.animateTo(\r\n        controller.offset - 150,\r\n        duration: const Duration(milliseconds: 500),\r\n        curve: Curves.easeInOut,\r\n      );\r\n    }\r\n\r\n    return LayoutBuilder(\r\n      builder: (context, constraints) {\r\n        WidgetsBinding.instance.addPostFrameCallback((_) {\r\n          if (controller.position.maxScrollExtent <= 0) {\r\n            showStartBtn.value = false;\r\n            showEndBtn.value = false;\r\n          } else {\r\n            showStartBtn.value = controller.position.pixels > controller.position.minScrollExtent;\r\n            showEndBtn.value = controller.position.pixels < controller.position.maxScrollExtent;\r\n          }\r\n        });\r\n        return Container(\r\n          padding: const EdgeInsets.only(bottom: 8),\r\n          height: 32,\r\n          child: PlatformUtils.isDesktop\r\n              ? Stack(\r\n                  children: [\r\n                    ListView.separated(\r\n                      controller: controller,\r\n                      padding: const EdgeInsets.symmetric(horizontal: 16),\r\n                      itemCount: values.length,\r\n                      scrollDirection: Axis.horizontal,\r\n                      itemBuilder: (context, index) => SettingDetailChip<T>(\r\n                        value: values[index],\r\n                        t: t,\r\n                        useEllipsis: useEllipsis,\r\n                        isPackageName: isPackageName,\r\n                      ),\r\n                      separatorBuilder: (context, index) => const Gap(8),\r\n                    ),\r\n                    Row(\r\n                      children: [\r\n                        if (showStartBtn.value) ScrollBtn(isStart: true, onTap: scrollToStart),\r\n                        const Spacer(),\r\n                        if (showEndBtn.value) ScrollBtn(isStart: false, onTap: scrollToEnd),\r\n                      ],\r\n                    ),\r\n                  ],\r\n                )\r\n              : ListView.separated(\r\n                  controller: controller,\r\n                  padding: const EdgeInsets.symmetric(horizontal: 16),\r\n                  itemCount: values.length,\r\n                  scrollDirection: Axis.horizontal,\r\n                  itemBuilder: (context, index) => SettingDetailChip<T>(\r\n                    value: values[index],\r\n                    t: t,\r\n                    useEllipsis: useEllipsis,\r\n                    isPackageName: isPackageName,\r\n                  ),\r\n                  separatorBuilder: (context, index) => const Gap(8),\r\n                ),\r\n        );\r\n      },\r\n    );\r\n  }\r\n}\r\n\r\nclass SettingDetailChip<T extends Object> extends ConsumerWidget {\r\n  const SettingDetailChip({\r\n    super.key,\r\n    required this.value,\r\n    required this.t,\r\n    required this.useEllipsis,\r\n    required this.isPackageName,\r\n  });\r\n\r\n  final T value;\r\n  final Map<String, String>? t;\r\n  final bool useEllipsis;\r\n  final bool isPackageName;\r\n\r\n  Widget valueByType(T value, ThemeData theme) {\r\n    if (value is MapEntry) {\r\n      return Row(\r\n        children: [\r\n          tText('${value.key}', theme),\r\n          VerticalDivider(width: 12, color: theme.colorScheme.onSurfaceVariant, indent: 3, endIndent: 3),\r\n          tText('${value.value}', theme),\r\n        ],\r\n      );\r\n    } else {\r\n      return tText('$value', theme);\r\n    }\r\n  }\r\n\r\n  Widget tText(String value, ThemeData theme) {\r\n    String text = value;\r\n    if (useEllipsis && value.length > 20) {\r\n      text = '${value.substring(0, 10)}...${value.substring(value.length - 10)}';\r\n    }\r\n    return Text(t == null ? text : t![text] ?? text, style: theme.textTheme.labelMedium);\r\n  }\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final theme = Theme.of(context);\r\n    return Container(\r\n      decoration: BoxDecoration(color: theme.colorScheme.surfaceVariant, borderRadius: BorderRadius.circular(8)),\r\n      child: isPackageName\r\n          ? AndroidAppInfo(packageName: '$value')\r\n          : Padding(padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: valueByType(value, theme)),\r\n    );\r\n  }\r\n}\r\n\r\nclass AndroidAppInfo extends HookConsumerWidget {\r\n  const AndroidAppInfo({super.key, required this.packageName});\r\n\r\n  final String packageName;\r\n\r\n  String useEllipsis() {\r\n    if (packageName.length > 20) {\r\n      return '${packageName.substring(0, 10)}...${packageName.substring(packageName.length - 10)}';\r\n    } else {\r\n      return packageName;\r\n    }\r\n  }\r\n\r\n  Future<AppInfo?> getAppInfo() async => await InstalledApps.getAppInfo(packageName, BuiltWith.flutter);\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final app = useFuture<AppInfo?>(useMemoized(() => getAppInfo(), [packageName]));\r\n    if (app.hasData && app.data != null) {\r\n      return Padding(\r\n        padding: const EdgeInsetsDirectional.fromSTEB(4, 4, 8, 4),\r\n        child: Row(\r\n          children: [\r\n            AspectRatio(\r\n              aspectRatio: 1.0,\r\n              child: CircleAvatar(backgroundColor: Colors.transparent, child: Image.memory(app.data!.icon!)),\r\n            ),\r\n            const Gap(4),\r\n            Text(app.data!.name, style: Theme.of(context).textTheme.labelMedium),\r\n          ],\r\n        ),\r\n      );\r\n    } else if (app.hasError || (app.hasData && app.data == null)) {\r\n      return Padding(\r\n        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),\r\n        child: Text(useEllipsis(), style: Theme.of(context).textTheme.labelMedium),\r\n      );\r\n    } else {\r\n      return const Padding(\r\n        padding: EdgeInsets.all(4),\r\n        child: AspectRatio(aspectRatio: 1.0, child: CircularProgressIndicator()),\r\n      );\r\n    }\r\n  }\r\n}\r\n\r\nclass ScrollBtn extends ConsumerWidget {\r\n  const ScrollBtn({super.key, required this.isStart, required this.onTap});\r\n\r\n  final bool isStart;\r\n  final GestureTapCallback? onTap;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final theme = Theme.of(context);\r\n    const radius = Radius.circular(4);\r\n    final borderRadius = isStart\r\n        ? const BorderRadiusDirectional.only(topEnd: radius, bottomEnd: radius)\r\n        : const BorderRadiusDirectional.only(topStart: radius, bottomStart: radius);\r\n    return Material(\r\n      borderRadius: borderRadius,\r\n      child: InkWell(\r\n        borderRadius: borderRadius.resolve(Directionality.of(context)),\r\n        onTap: onTap,\r\n        child: Container(\r\n          width: 48,\r\n          height: 24,\r\n          decoration: BoxDecoration(\r\n            color: theme.colorScheme.primaryContainer,\r\n            borderRadius: borderRadius,\r\n            boxShadow: [BoxShadow(color: theme.colorScheme.shadow, blurRadius: 12, offset: const Offset(0, 3))],\r\n          ),\r\n          child: Icon(\r\n            isStart ? Icons.arrow_left_rounded : Icons.arrow_right_rounded,\r\n            color: theme.colorScheme.onPrimaryContainer,\r\n          ),\r\n        ),\r\n      ),\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/widget/setting_divider.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass SettingDivider extends ConsumerWidget {\r\n  const SettingDivider({super.key, this.title});\r\n\r\n  final String? title;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final theme = Theme.of(context);\r\n    if (title == null) return const Divider(indent: 16, endIndent: 16, height: 1);\r\n    return Row(\r\n      children: [\r\n        const Expanded(child: Divider(indent: 16, endIndent: 8, height: 1)),\r\n        const Icon(size: 16, Icons.warning_rounded, color: Colors.amber),\r\n        const Gap(2),\r\n        Text(title!, style: theme.textTheme.titleSmall!.copyWith(color: theme.colorScheme.onSurface)),\r\n        const Expanded(child: Divider(indent: 8, endIndent: 16, height: 1)),\r\n      ],\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/widget/setting_generic_list.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:gap/gap.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/features/route_rules/widget/setting_detail_chips.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass SettingGenericList<T extends Object> extends ConsumerWidget {\r\n  const SettingGenericList({\r\n    super.key,\r\n    required this.title,\r\n    required this.values,\r\n    required this.onTap,\r\n    this.useEllipsis = false,\r\n    this.isPackageName = false,\r\n    this.showPlatformWarning = false,\r\n  });\r\n\r\n  final String title;\r\n  final List<T> values;\r\n  final GestureTapCallback? onTap;\r\n  final bool useEllipsis;\r\n  final bool isPackageName;\r\n  final bool showPlatformWarning;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    final theme = Theme.of(context);\r\n    return Material(\r\n      child: InkWell(\r\n        onTap: onTap,\r\n        child: Column(\r\n          crossAxisAlignment: CrossAxisAlignment.start,\r\n          children: [\r\n            ListTile(\r\n              title: showPlatformWarning\r\n                  ? Column(\r\n                      crossAxisAlignment: CrossAxisAlignment.start,\r\n                      children: [\r\n                        Row(\r\n                          children: [\r\n                            const Icon(size: 16, Icons.warning_rounded, color: Colors.amber),\r\n                            const Gap(2),\r\n                            Text(\r\n                              t.pages.settings.routing.routeRule.rule.notAvailabeInThisPlatform,\r\n                              style: theme.textTheme.labelSmall!.copyWith(color: theme.colorScheme.onSurfaceVariant),\r\n                              overflow: TextOverflow.ellipsis,\r\n                              maxLines: 1,\r\n                            ),\r\n                          ],\r\n                        ),\r\n                        Text(title),\r\n                      ],\r\n                    )\r\n                  : Text(title),\r\n              trailing: Text('${values.length}'),\r\n            ),\r\n            if (values.isNotEmpty)\r\n              SettingDetailChips<T>(values: values, useEllipsis: useEllipsis, isPackageName: isPackageName),\r\n          ],\r\n        ),\r\n      ),\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/widget/setting_radio.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass SettingRadio<T> extends ConsumerWidget {\r\n  const SettingRadio({\r\n    super.key,\r\n    required this.title,\r\n    required this.values,\r\n    required this.value,\r\n    required this.setValue,\r\n    this.defaultValue,\r\n    this.t,\r\n  });\r\n\r\n  final String title;\r\n  final List<T> values;\r\n  final T value;\r\n  final Function(T value) setValue;\r\n  final T? defaultValue;\r\n  final Map<String, String>? t;\r\n\r\n  String textWithTranslation(T e) {\r\n    if (t == null) return '$e';\r\n    return t!['$e'] ?? '$e';\r\n  }\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    return ListTile(\r\n      title: Text(title),\r\n      subtitle: Text(textWithTranslation(value)),\r\n      onTap: () async {\r\n        final result = await ref\r\n            .read(dialogNotifierProvider.notifier)\r\n            .showSettingRadio<T>(title: title, values: values, value: value, defaultValue: defaultValue, t: t);\r\n        if (result is T) setValue(result);\r\n      },\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/route_rules/widget/setting_text.dart",
    "content": "import 'package:flutter/material.dart';\r\nimport 'package:hiddify/core/localization/translations.dart';\r\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass SettingText extends ConsumerWidget {\r\n  const SettingText({\r\n    super.key,\r\n    required this.title,\r\n    required this.value,\r\n    required this.setValue,\r\n    this.defaultValue,\r\n    this.validator,\r\n  });\r\n\r\n  final String title;\r\n  final String value;\r\n  final Function(String value) setValue;\r\n  final String? defaultValue;\r\n  final FormFieldValidator<String>? validator;\r\n\r\n  @override\r\n  Widget build(BuildContext context, WidgetRef ref) {\r\n    final t = ref.watch(translationsProvider).requireValue;\r\n    return ListTile(\r\n      title: Text(title),\r\n      subtitle: Text(value.isEmpty ? t.common.empty : value),\r\n      onTap: () async {\r\n        final result = await ref\r\n            .read(dialogNotifierProvider.notifier)\r\n            .showSettingText(lable: title, value: value, defaultValue: defaultValue, validator: validator);\r\n        if (result is String) setValue(result);\r\n      },\r\n    );\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/features/settings/data/battery_optimization_repository.dart",
    "content": "import 'package:flutter/services.dart';\nimport 'package:hiddify/core/utils/exception_handler.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:loggy/loggy.dart';\n\nabstract interface class BatteryOptimizationRepository {\n  Future<bool?> isIgnoringBatteryOptimizations();\n  Future<bool?> requestIgnoreBatteryOptimizations();\n}\n\nclass BatteryOptimizationRepositoryImpl with ExceptionHandler, InfraLogger implements BatteryOptimizationRepository {\n  final _methodChannel = const MethodChannel(\"com.hiddify.app/platform\");\n\n  @override\n  Future<bool?> isIgnoringBatteryOptimizations() async {\n    bool? result;\n    try {\n      loggy.debug(\"checking battery optimization status\");\n      result = await _methodChannel.invokeMethod<bool>(\"is_ignoring_battery_optimizations\");\n      loggy.debug(\"is ignoring battery optimizations? [$result]\");\n    } catch (e) {\n      loggy.log(LogLevel.error, e.toString());\n    }\n    return result;\n  }\n\n  @override\n  Future<bool?> requestIgnoreBatteryOptimizations() async {\n    bool? result;\n    try {\n      loggy.debug(\"requesting ignore battery optimization\");\n      result = await _methodChannel.invokeMethod<bool>(\"request_ignore_battery_optimizations\");\n      loggy.debug(\"ignore battery optimization result: [$result]\");\n    } catch (e) {\n      loggy.log(LogLevel.error, e.toString());\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/data/config_option_data_providers.dart",
    "content": "import 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'config_option_data_providers.g.dart';\n\n@Riverpod(keepAlive: true)\nConfigOptionRepository configOptionRepository(Ref ref) {\n  return ConfigOptionRepository(\n    preferences: ref.watch(sharedPreferencesProvider).requireValue,\n    getConfigOptions: () => ref.read(ConfigOptions.singboxConfigOptions),\n  );\n}\n"
  },
  {
    "path": "lib/features/settings/data/config_option_repository.dart",
    "content": "import 'package:dartx/dartx.dart';\nimport 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/model/optional_range.dart';\nimport 'package:hiddify/core/model/region.dart';\nimport 'package:hiddify/core/utils/exception_handler.dart';\nimport 'package:hiddify/core/utils/json_converters.dart';\nimport 'package:hiddify/core/utils/preferences_utils.dart';\nimport 'package:hiddify/features/log/model/log_level.dart';\nimport 'package:hiddify/features/profile/data/profile_parser.dart';\nimport 'package:hiddify/features/settings/model/config_option_failure.dart';\nimport 'package:hiddify/singbox/model/singbox_config_enum.dart';\nimport 'package:hiddify/singbox/model/singbox_config_option.dart';\nimport 'package:hiddify/singbox/model/singbox_rule.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\nabstract class ConfigOptions {\n  static final serviceMode = PreferencesNotifier.create<ServiceMode, String>(\n    \"service-mode\",\n    ServiceMode.defaultMode,\n    mapFrom: (value) => ServiceMode.choices.firstWhere((e) => e.key == value),\n    mapTo: (value) => value.key,\n  );\n\n  static final balancerStrategy = PreferencesNotifier.create<BalancerStrategy, String>(\n    \"balancer-strategy\",\n    BalancerStrategy.roundRobin,\n    mapFrom: (value) => BalancerStrategy.values.firstWhere((e) => e.key == value),\n    mapTo: (value) => value.key,\n  );\n\n  static final region = PreferencesNotifier.create<Region, String>(\n    \"region\",\n    Region.other,\n    mapFrom: Region.values.byName,\n    mapTo: (value) => value.name,\n  );\n  static final useXrayCoreWhenPossible = PreferencesNotifier.create<bool, bool>(\"use-xray-core-when-possible\", false);\n  static final blockAds = PreferencesNotifier.create<bool, bool>(\"block-ads\", false);\n  static final logLevel = PreferencesNotifier.create<LogLevel, String>(\n    \"log-level\",\n    LogLevel.warn,\n    mapFrom: LogLevel.values.byName,\n    mapTo: (value) => value.name,\n  );\n\n  static final resolveDestination = PreferencesNotifier.create<bool, bool>(\"resolve-destination\", false);\n\n  static final ipv6Mode = PreferencesNotifier.create<IPv6Mode, String>(\n    \"ipv6-mode\",\n    IPv6Mode.disable,\n    mapFrom: (value) => IPv6Mode.values.firstWhere((e) => e.key == value),\n    mapTo: (value) => value.key,\n  );\n\n  static final remoteDnsAddress = PreferencesNotifier.create<String, String>(\n    \"remote-dns-address\",\n    \"tcp://8.8.8.8\",\n    possibleValues: List.of([\n      \"local\",\n      // \"udp://223.5.5.5\",\n      // \"udp://1.1.1.1\",\n      // \"udp://1.1.1.2\",\n      \"tcp://8.8.8.8\",\n      \"tcp://1.1.1.1\",\n      \"https://1.1.1.1/dns-query\",\n      \"https://dns.cloudflare.com/dns-query\",\n      \"tcp://4.4.2.2\",\n    ]),\n    validator: (value) => value.isNotBlank,\n  );\n\n  static final remoteDnsDomainStrategy = PreferencesNotifier.create<DomainStrategy, String>(\n    \"remote-dns-domain-strategy\",\n    DomainStrategy.auto,\n    mapFrom: (value) => DomainStrategy.values.firstWhere((e) => e.key == value),\n    mapTo: (value) => value.key,\n  );\n\n  static final directDnsAddress = PreferencesNotifier.create<String, String>(\n    \"direct-dns-address\",\n    \"udp://1.1.1.1\",\n    possibleValues: List.of([\n      \"local\",\n      \"udp://223.5.5.5\",\n      \"udp://1.1.1.1\",\n      \"udp://1.1.1.2\",\n      \"tcp://1.1.1.1\",\n      \"https://1.1.1.1/dns-query\",\n      \"https://dns.cloudflare.com/dns-query\",\n      \"4.4.2.2\",\n      \"8.8.8.8\",\n    ]),\n    defaultValueFunction: (ref) => ref.read(region) == Region.cn ? \"223.5.5.5\" : \"1.1.1.1\",\n    validator: (value) => value.isNotBlank,\n  );\n\n  static final directDnsDomainStrategy = PreferencesNotifier.create<DomainStrategy, String>(\n    \"direct-dns-domain-strategy\",\n    DomainStrategy.auto,\n    mapFrom: (value) => DomainStrategy.values.firstWhere((e) => e.key == value),\n    mapTo: (value) => value.key,\n  );\n\n  static final mixedPort = PreferencesNotifier.create<int, int>(\n    \"mixed-port\",\n    12334,\n    validator: (value) => isPort(value.toString()),\n  );\n\n  static final tproxyPort = PreferencesNotifier.create<int, int>(\n    \"tproxy-port\",\n    12335,\n    validator: (value) => isPort(value.toString()),\n  );\n  static final redirectPort = PreferencesNotifier.create<int, int>(\n    \"redirect-port\",\n    12336,\n    validator: (value) => isPort(value.toString()),\n  );\n  static final directPort = PreferencesNotifier.create<int, int>(\n    \"direct-port\",\n    12337,\n    validator: (value) => isPort(value.toString()),\n  );\n\n  static final tunImplementation = PreferencesNotifier.create<TunImplementation, String>(\n    \"tun-implementation\",\n    TunImplementation.gvisor,\n    mapFrom: TunImplementation.values.byName,\n    mapTo: (value) => value.name,\n  );\n\n  static final mtu = PreferencesNotifier.create<int, int>(\"mtu\", 9000);\n\n  static final strictRoute = PreferencesNotifier.create<bool, bool>(\"strict-route\", true);\n\n  static final connectionTestUrl = PreferencesNotifier.create<String, String>(\n    \"connection-test-url\",\n    \"http://captive.apple.com/hotspot-detect.html\",\n    possibleValues: List.of([\n      \"http://connectivitycheck.gstatic.com/generate_204\",\n      \"http://www.gstatic.com/generate_204\",\n      \"https://www.gstatic.com/generate_204\",\n      \"http://cp.cloudflare.com\",\n      \"http://kernel.org\",\n      \"http://detectportal.firefox.com\",\n      \"http://captive.apple.com/hotspot-detect.html\",\n      \"https://1.1.1.1\",\n      \"http://1.1.1.1\",\n    ]),\n    validator: (value) => value.isNotBlank && isUrl(value),\n  );\n\n  static final urlTestInterval = PreferencesNotifier.create<Duration, int>(\n    \"url-test-interval\",\n    const Duration(minutes: 10),\n    mapFrom: const IntervalInSecondsConverter().fromJson,\n    mapTo: const IntervalInSecondsConverter().toJson,\n  );\n\n  static final enableClashApi = PreferencesNotifier.create<bool, bool>(\"enable-clash-api\", true);\n\n  static final clashApiPort = PreferencesNotifier.create<int, int>(\n    \"clash-api-port\",\n    16756,\n    validator: (value) => isPort(value.toString()),\n  );\n\n  static final bypassLan = PreferencesNotifier.create<bool, bool>(\"bypass-lan\", false);\n\n  static final allowConnectionFromLan = PreferencesNotifier.create<bool, bool>(\"allow-connection-from-lan\", false);\n\n  static final enableFakeDns = PreferencesNotifier.create<bool, bool>(\"enable-fake-dns\", false);\n\n  // static final enableDnsRouting = PreferencesNotifier.create<bool, bool>(\"enable-dns-routing\", true);\n\n  static final independentDnsCache = PreferencesNotifier.create<bool, bool>(\"independent-dns-cache\", true);\n\n  static final enableTlsFragment = PreferencesNotifier.create<bool, bool>(\"enable-tls-fragment\", false);\n\n  static final fragmentPackets = PreferencesNotifier.create<String, String>(\n    \"fragment-packets\",\n    \"tlshello\",\n    possibleValues: [\"tlshello\", \"1-1\", \"1-2\", \"1-3\", \"1-4\", \"1-5\"],\n  );\n\n  static final tlsFragmentSize = PreferencesNotifier.create<OptionalRange, String>(\n    \"tls-fragment-size\",\n    const OptionalRange(min: 10, max: 30),\n    mapFrom: OptionalRange.parse,\n    mapTo: const OptionalRangeJsonConverter().toJson,\n  );\n\n  static final tlsFragmentSleep = PreferencesNotifier.create<OptionalRange, String>(\n    \"tls-fragment-sleep\",\n    const OptionalRange(min: 2, max: 8),\n    mapFrom: OptionalRange.parse,\n    mapTo: const OptionalRangeJsonConverter().toJson,\n  );\n\n  static final enableTlsMixedSniCase = PreferencesNotifier.create<bool, bool>(\"enable-tls-mixed-sni-case\", false);\n\n  static final enableTlsPadding = PreferencesNotifier.create<bool, bool>(\"enable-tls-padding\", false);\n\n  static final tlsPaddingSize = PreferencesNotifier.create<OptionalRange, String>(\n    \"tls-padding-size\",\n    const OptionalRange(min: 1, max: 1500),\n    mapFrom: OptionalRange.parse,\n    mapTo: const OptionalRangeJsonConverter().toJson,\n  );\n\n  static final enableMux = PreferencesNotifier.create<bool, bool>(\"enable-mux\", false);\n\n  static final muxPadding = PreferencesNotifier.create<bool, bool>(\"mux-padding\", false);\n\n  static final muxMaxStreams = PreferencesNotifier.create<int, int>(\n    \"mux-max-streams\",\n    8,\n    validator: (value) => value > 0,\n  );\n\n  static final muxProtocol = PreferencesNotifier.create<MuxProtocol, String>(\n    \"mux-protocol\",\n    MuxProtocol.h2mux,\n    mapFrom: MuxProtocol.values.byName,\n    mapTo: (value) => value.name,\n  );\n\n  static final enableWarp = PreferencesNotifier.create<bool, bool>(\"enable-warp\", false);\n\n  static final warpDetourMode = PreferencesNotifier.create<WarpDetourMode, String>(\n    \"warp-detour-mode\",\n    WarpDetourMode.warpOverProxy,\n    mapFrom: WarpDetourMode.values.byName,\n    mapTo: (value) => value.name,\n  );\n\n  static final warpLicenseKey = PreferencesNotifier.create<String, String>(\"warp-license-key\", \"\");\n  static final warp2LicenseKey = PreferencesNotifier.create<String, String>(\"warp2s-license-key\", \"\");\n\n  static final warpAccountId = PreferencesNotifier.create<String, String>(\"warp-account-id\", \"\");\n  static final warp2AccountId = PreferencesNotifier.create<String, String>(\"warp2-account-id\", \"\");\n\n  static final warpAccessToken = PreferencesNotifier.create<String, String>(\"warp-access-token\", \"\");\n  static final warp2AccessToken = PreferencesNotifier.create<String, String>(\"warp2-access-token\", \"\");\n\n  static final warpCleanIp = PreferencesNotifier.create<String, String>(\"warp-clean-ip\", \"auto\");\n\n  static final warpPort = PreferencesNotifier.create<int, int>(\n    \"warp-port\",\n    0,\n    validator: (value) => isPort(value.toString()),\n  );\n\n  static final warpNoise = PreferencesNotifier.create<OptionalRange, String>(\n    \"warp-noise\",\n    const OptionalRange(min: 1, max: 3),\n    mapFrom: (value) => OptionalRange.parse(value, allowEmpty: true),\n    mapTo: const OptionalRangeJsonConverter().toJson,\n  );\n  static final warpNoiseMode = PreferencesNotifier.create<String, String>(\"warp-noise-mode\", \"m4\");\n\n  static final warpNoiseDelay = PreferencesNotifier.create<OptionalRange, String>(\n    \"warp-noise-delay\",\n    const OptionalRange(min: 10, max: 30),\n    mapFrom: (value) => OptionalRange.parse(value, allowEmpty: true),\n    mapTo: const OptionalRangeJsonConverter().toJson,\n  );\n  static final warpNoiseSize = PreferencesNotifier.create<OptionalRange, String>(\n    \"warp-noise-size\",\n    const OptionalRange(min: 10, max: 30),\n    mapFrom: (value) => OptionalRange.parse(value, allowEmpty: true),\n    mapTo: const OptionalRangeJsonConverter().toJson,\n  );\n\n  static final warpWireguardConfig = PreferencesNotifier.create<String, String>(\"warp-wireguard-config\", \"\");\n  static final warp2WireguardConfig = PreferencesNotifier.create<String, String>(\"warp2-wireguard-config\", \"\");\n\n  static final hasExperimentalFeatures = Provider.autoDispose<bool>((ref) {\n    // final mode = ref.watch(serviceMode);\n    // if (PlatformUtils.isDesktop && mode == ServiceMode.tun) {\n    //   return true;\n    // }\n    // if (ref.watch(enableTlsFragment) || ref.watch(enableTlsMixedSniCase) || ref.watch(enableTlsPadding) || ref.watch(enableMux) || ref.watch(enableWarp) || ref.watch(bypassLan) || ref.watch(allowConnectionFromLan)) {\n    //   return true;\n    // }\n\n    return false;\n  });\n\n  /// preferences to exclude from share and export\n  static final privatePreferencesKeys = {\n    \"warp.license-key\",\n    \"warp.access-token\",\n    \"warp.account-id\",\n    \"warp.wireguard-config\",\n    \"warp2.license-key\",\n    \"warp2.access-token\",\n    \"warp2.account-id\",\n    \"warp2.wireguard-config\",\n  };\n\n  static final Map<String, StateNotifierProvider<PreferencesNotifier, dynamic>> preferences = {\n    \"region\": region,\n    \"balancer-strategy\": balancerStrategy,\n    \"block-ads\": blockAds,\n    \"use-xray-core-when-possible\": useXrayCoreWhenPossible,\n    \"service-mode\": serviceMode,\n    \"log-level\": logLevel,\n    \"resolve-destination\": resolveDestination,\n    \"ipv6-mode\": ipv6Mode,\n    \"remote-dns-address\": remoteDnsAddress,\n    \"remote-dns-domain-strategy\": remoteDnsDomainStrategy,\n    \"direct-dns-address\": directDnsAddress,\n    \"direct-dns-domain-strategy\": directDnsDomainStrategy,\n    \"mixed-port\": mixedPort,\n    \"tproxy-port\": tproxyPort,\n    \"direct-port\": directPort,\n    \"redirect-port\": redirectPort,\n    \"tun-implementation\": tunImplementation,\n    \"mtu\": mtu,\n    \"strict-route\": strictRoute,\n    \"connection-test-url\": connectionTestUrl,\n    \"url-test-interval\": urlTestInterval,\n    \"clash-api-port\": clashApiPort,\n    \"bypass-lan\": bypassLan,\n    \"allow-connection-from-lan\": allowConnectionFromLan,\n    // \"enable-dns-routing\": enableDnsRouting,\n\n    // mux\n    // \"mux.enable\": enableMux,\n    // \"mux.padding\": muxPadding,\n    // \"mux.max-streams\": muxMaxStreams,\n    // \"mux.protocol\": muxProtocol,\n\n    // tls-tricks\n    \"tls-tricks.enable-fragment\": enableTlsFragment,\n    \"tls-tricks.fragment-packets\": fragmentPackets,\n    \"tls-tricks.fragment-size\": tlsFragmentSize,\n    \"tls-tricks.fragment-sleep\": tlsFragmentSleep,\n    \"tls-tricks.mixed-sni-case\": enableTlsMixedSniCase,\n    \"tls-tricks.enable-padding\": enableTlsPadding,\n    \"tls-tricks.padding-size\": tlsPaddingSize,\n\n    // warp\n    \"warp.enable\": enableWarp,\n    \"warp.mode\": warpDetourMode,\n    \"warp.license-key\": warpLicenseKey,\n    \"warp.account-id\": warpAccountId,\n    \"warp.access-token\": warpAccessToken,\n    \"warp.clean-ip\": warpCleanIp,\n    \"warp.clean-port\": warpPort,\n    \"warp.noise\": warpNoise,\n    \"warp.noise-size\": warpNoiseSize,\n    \"warp.noise-mode\": warpNoiseMode,\n    \"warp.noise-delay\": warpNoiseDelay,\n    \"warp.wireguard-config\": warpWireguardConfig,\n    \"warp2.license-key\": warp2LicenseKey,\n    \"warp2.account-id\": warp2AccountId,\n    \"warp2.access-token\": warp2AccessToken,\n    \"warp2.wireguard-config\": warp2WireguardConfig,\n  };\n\n  static final singboxConfigOptions = Provider<SingboxConfigOption>((ref) {\n    // final region = ref.watch(Preferences.region);\n    final rules = <SingboxRule>[];\n    // final rules = switch (region) {\n    //   Region.ir => [\n    //       const SingboxRule(\n    //         domains: \"domain:.ir,geosite:ir\",\n    //         ip: \"geoip:ir\",\n    //         outbound: RuleOutbound.bypass,\n    //       ),\n    //     ],\n    //   Region.cn => [\n    //       const SingboxRule(\n    //         domains: \"domain:.cn,geosite:cn\",\n    //         ip: \"geoip:cn\",\n    //         outbound: RuleOutbound.bypass,\n    //       ),\n    //     ],\n    //   Region.ru => [\n    //       const SingboxRule(\n    //         domains: \"domain:.ru\",\n    //         ip: \"geoip:ru\",\n    //         outbound: RuleOutbound.bypass,\n    //       ),\n    //     ],\n    //   Region.af => [\n    //       const SingboxRule(\n    //         domains: \"domain:.af,geosite:af\",\n    //         ip: \"geoip:af\",\n    //         outbound: RuleOutbound.bypass,\n    //       ),\n    //     ],\n    //   Region.id => [\n    //       const SingboxRule(\n    //         domains: \"domain:.id,geosite:id\",\n    //         ip: \"geoip:id\",\n    //         outbound: RuleOutbound.bypass,\n    //       ),\n    //     ],\n    //   _ => <SingboxRule>[],\n    // };\n\n    final mode = ref.watch(serviceMode);\n    // final reg = ref.watch(Preferences.region.notifier).raw();\n\n    return SingboxConfigOption(\n      region: ref.watch(region).name,\n      balancerStrategy: ref.watch(balancerStrategy),\n      blockAds: ref.watch(blockAds),\n      useXrayCoreWhenPossible: ref.watch(useXrayCoreWhenPossible),\n      executeConfigAsIs: false,\n      logLevel: ref.watch(logLevel),\n      resolveDestination: ref.watch(resolveDestination),\n      ipv6Mode: ref.watch(ipv6Mode),\n      remoteDnsAddress: ref.watch(remoteDnsAddress),\n      remoteDnsDomainStrategy: ref.watch(remoteDnsDomainStrategy),\n      directDnsAddress: ref.watch(directDnsAddress),\n      directDnsDomainStrategy: ref.watch(directDnsDomainStrategy),\n      mixedPort: ref.watch(mixedPort),\n      tproxyPort: ref.watch(tproxyPort),\n      directPort: ref.watch(directPort),\n      redirectPort: ref.watch(redirectPort),\n      tunImplementation: ref.watch(tunImplementation),\n      mtu: ref.watch(mtu),\n      strictRoute: ref.watch(strictRoute),\n      connectionTestUrl: ref.watch(connectionTestUrl),\n      urlTestInterval: ref.watch(urlTestInterval),\n      enableClashApi: ref.watch(enableClashApi),\n      clashApiPort: ref.watch(clashApiPort),\n      enableTun: mode == ServiceMode.tun,\n      // enableTunService: mode == false, //ServiceMode.tunService,\n      setSystemProxy: mode == ServiceMode.systemProxy,\n      bypassLan: ref.watch(bypassLan),\n      allowConnectionFromLan: ref.watch(allowConnectionFromLan),\n      enableFakeDns: ref.watch(enableFakeDns),\n      // enableDnsRouting: ref.watch(enableDnsRouting),\n      independentDnsCache: ref.watch(independentDnsCache),\n      // mux: SingboxMuxOption(\n      //   enable: ref.watch(enableMux),\n      //   padding: ref.watch(muxPadding),\n      //   maxStreams: ref.watch(muxMaxStreams),\n      //   protocol: ref.watch(muxProtocol),\n      // ),\n      tlsTricks: SingboxTlsTricks(\n        enableFragment: ref.watch(enableTlsFragment),\n        fragmentSize: ref.watch(tlsFragmentSize),\n        fragmentSleep: ref.watch(tlsFragmentSleep),\n        mixedSniCase: ref.watch(enableTlsMixedSniCase),\n        enablePadding: ref.watch(enableTlsPadding),\n        paddingSize: ref.watch(tlsPaddingSize),\n      ),\n      warp: SingboxWarpOption(\n        enable: ref.watch(enableWarp),\n        mode: ref.watch(warpDetourMode),\n        wireguardConfig: ref.watch(warpWireguardConfig),\n        licenseKey: ref.watch(warpLicenseKey),\n        accountId: ref.watch(warpAccountId),\n        accessToken: ref.watch(warpAccessToken),\n        cleanIp: ref.watch(warpCleanIp),\n        cleanPort: ref.watch(warpPort),\n        noise: ref.watch(warpNoise),\n        noiseMode: ref.watch(warpNoiseMode),\n        noiseSize: ref.watch(warpNoiseSize),\n        noiseDelay: ref.watch(warpNoiseDelay),\n      ),\n      warp2: SingboxWarpOption(\n        enable: ref.watch(enableWarp),\n        mode: ref.watch(warpDetourMode),\n        wireguardConfig: ref.watch(warp2WireguardConfig),\n        licenseKey: ref.watch(warp2LicenseKey),\n        accountId: ref.watch(warp2AccountId),\n        accessToken: ref.watch(warp2AccessToken),\n        cleanIp: ref.watch(warpCleanIp),\n        cleanPort: ref.watch(warpPort),\n        noise: ref.watch(warpNoise),\n        noiseMode: ref.watch(warpNoiseMode),\n        noiseSize: ref.watch(warpNoiseSize),\n        noiseDelay: ref.watch(warpNoiseDelay),\n      ),\n      rules: rules,\n    );\n  });\n}\n\nclass ConfigOptionRepository with ExceptionHandler, InfraLogger {\n  ConfigOptionRepository({required this.preferences, required SingboxConfigOption Function() getConfigOptions})\n    : _getConfigOptions = getConfigOptions;\n\n  final SharedPreferences preferences;\n  final SingboxConfigOption Function() _getConfigOptions;\n\n  Either<ConfigOptionFailure, SingboxConfigOption> fullOptions() =>\n      Either.tryCatch(() => _getConfigOptions(), ConfigOptionFailure.unexpected);\n\n  Either<ConfigOptionFailure, SingboxConfigOption> fullOptionsOverrided(String? profileOverride) =>\n      Either.tryCatch(() => _getConfigOptions(), ConfigOptionFailure.unexpected).flatMap(\n        (options) => Either.tryCatch(() {\n          final json = ProfileParser.applyProfileOverride(options.toJson(), profileOverride);\n          return SingboxConfigOption.fromJson(json);\n        }, ConfigOptionFailure.unexpected),\n      );\n}\n"
  },
  {
    "path": "lib/features/settings/model/config_option_failure.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\n\npart 'config_option_failure.freezed.dart';\n\n@freezed\nsealed class ConfigOptionFailure with _$ConfigOptionFailure, Failure {\n  const ConfigOptionFailure._();\n\n  @With<UnexpectedFailure>()\n  const factory ConfigOptionFailure.unexpected([Object? error, StackTrace? stackTrace]) = ConfigOptionUnexpectedFailure;\n\n  @With<ExpectedFailure>()\n  const factory ConfigOptionFailure.missingWarp() = MissingWarpConfigFailure;\n\n  @override\n  ({String type, String? message}) present(TranslationsEn t) {\n    return switch (this) {\n      ConfigOptionUnexpectedFailure() => (type: t.errors.unexpected, message: null),\n      MissingWarpConfigFailure() => (type: t.pages.settings.warp.missingConfig, message: null),\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/model/settings_failure.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\n\npart 'settings_failure.freezed.dart';\n\n@freezed\nsealed class SettingsFailure with _$SettingsFailure, Failure {\n  const SettingsFailure._();\n\n  @With<UnexpectedFailure>()\n  const factory SettingsFailure.unexpected([Object? error, StackTrace? stackTrace]) = SettingsUnexpectedFailure;\n\n  @override\n  ({String type, String? message}) present(TranslationsEn t) {\n    return switch (this) {\n      SettingsUnexpectedFailure() => (type: t.errors.unexpected, message: null),\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/notifier/battery_optimization/battery_optimizations_notifier.dart",
    "content": "import 'package:hiddify/features/settings/data/battery_optimization_repository.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'battery_optimizations_notifier.g.dart';\n\n@riverpod\nclass BatteryOptimizationNotifier extends _$BatteryOptimizationNotifier {\n  @override\n  Future<bool> build() async {\n    return await BatteryOptimizationRepositoryImpl().isIgnoringBatteryOptimizations() ?? false;\n  }\n\n  Future<void> requestToIgnore() async {\n    state = const AsyncLoading();\n    await BatteryOptimizationRepositoryImpl().requestIgnoreBatteryOptimizations();\n    Future.delayed(const Duration(seconds: 1));\n    ref.invalidateSelf();\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/notifier/config_option/config_option_notifier.dart",
    "content": "import 'dart:convert';\nimport 'dart:io';\n\nimport 'package:dartx/dartx_io.dart';\nimport 'package:file_picker/file_picker.dart';\nimport 'package:flutter/services.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/features/connection/data/connection_data_providers.dart';\nimport 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/features/profile/notifier/active_profile_notifier.dart';\nimport 'package:hiddify/features/proxy/active/active_proxy_notifier.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hiddify/utils/platform_utils.dart';\nimport 'package:json_path/json_path.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'config_option_notifier.g.dart';\n\n@Riverpod(keepAlive: true)\nclass ConfigOptionNotifier extends _$ConfigOptionNotifier with AppLogger {\n  @override\n  Future<bool> build() async {\n    final serviceRunning = await ref.watch(serviceRunningProvider.future);\n    final serviceSingboxOptions = ref.read(connectionRepositoryProvider).configOptionsSnapshot;\n\n    ref.listen(ConfigOptions.singboxConfigOptions, (previous, next) async {\n      if (!serviceRunning || previous == null) return;\n      if (next != previous && next != serviceSingboxOptions) {\n        if (_lastUpdate == null || DateTime.now().difference(_lastUpdate!) > const Duration(milliseconds: 100)) {\n          _lastUpdate = DateTime.now();\n          if (serviceSingboxOptions?.enableTun != next.enableTun) {\n            loggy.debug(\"tun option changed, reconnecting\");\n            await ref.read(connectionNotifierProvider.notifier).toggleConnection();\n            await ref.read(connectionNotifierProvider.notifier).toggleConnection();\n          } else {\n            final activeProfile = await ref.read(activeProfileProvider.future);\n            return await ref.read(connectionNotifierProvider.notifier).reconnect(activeProfile);\n          }\n          state = AsyncData(false);\n        }\n      }\n    }, fireImmediately: true);\n    return false;\n  }\n\n  DateTime? _lastUpdate;\n\n  Future<String?> _exportJson(bool excludePrivate) async {\n    try {\n      final options = ref.read(ConfigOptions.singboxConfigOptions);\n      Map map = options.toJson();\n      if (excludePrivate) {\n        for (final key in ConfigOptions.privatePreferencesKeys) {\n          final query = key.split('.').map((e) => '[\"$e\"]').join();\n          final res = JsonPath('\\$$query').read(map).firstOrNull;\n          if (res != null) {\n            map = res.pointer.remove(map)! as Map;\n          }\n        }\n      }\n      const encoder = JsonEncoder.withIndent('  ');\n      return encoder.convert(map);\n    } catch (e, st) {\n      loggy.warning(\"error creating config options json\", e, st);\n      return null;\n    }\n  }\n\n  Future<bool> exportJsonClipboard({bool excludePrivate = true}) async {\n    final t = ref.read(translationsProvider).requireValue;\n    try {\n      final json = await _exportJson(excludePrivate);\n      if (json == null) return false;\n      await Clipboard.setData(ClipboardData(text: json));\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.export.clipboard.success);\n      return true;\n    } on PlatformException {\n      ref\n          .read(inAppNotificationControllerProvider)\n          .showInfoToast(t.common.msg.export.clipboard.contentTooLarge, duration: const Duration(seconds: 5));\n      return false;\n    } catch (e, st) {\n      loggy.warning(\"error exporting config options to clipboard\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.export.clipboard.failure);\n      return false;\n    }\n  }\n\n  Future<bool> exportJsonFile({bool excludePrivate = true}) async {\n    final t = ref.read(translationsProvider).requireValue;\n    try {\n      final json = await _exportJson(excludePrivate);\n      if (json == null) return false;\n      final bytes = utf8.encode(json);\n      final outputFile = await FilePicker.platform.saveFile(\n        fileName: 'options.json',\n        type: FileType.custom,\n        allowedExtensions: ['json'],\n        bytes: bytes,\n      );\n      if (outputFile == null) return false;\n      if (PlatformUtils.isDesktop) {\n        final file = File(outputFile);\n        if (file.extension != '.json') return false;\n        if (!await file.exists()) await file.parent.create(recursive: true);\n        await file.writeAsBytes(bytes);\n      }\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.export.file.success);\n      return true;\n    } catch (e, st) {\n      loggy.warning(\"error exporting config options to json file\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.export.file.failure);\n      return false;\n    }\n  }\n\n  Future<void> _importJson(String input) async {\n    if (jsonDecode(input) case final Map<String, dynamic> map) {\n      for (final option in ConfigOptions.preferences.entries) {\n        final query = option.key.split('.').map((e) => '[\"$e\"]').join();\n        final res = JsonPath('\\$$query').read(map).firstOrNull;\n        if (res?.value case final value?) {\n          try {\n            await ref.read(option.value.notifier).updateRaw(value);\n          } catch (e) {\n            loggy.debug(\"error updating [${option.key}]: $e\", e);\n          }\n        }\n      }\n    }\n  }\n\n  Future<bool> importFromClipboard() async {\n    final t = ref.read(translationsProvider).requireValue;\n    try {\n      final input = await Clipboard.getData(Clipboard.kTextPlain).then((value) => value?.text);\n      if (input == null) return false;\n      await _importJson(input);\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.import.success);\n      return true;\n    } catch (e, st) {\n      loggy.warning(\"error importing config options from clipboard\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.import.failure);\n      return false;\n    }\n  }\n\n  Future<bool> importFromJsonFile() async {\n    final t = ref.read(translationsProvider).requireValue;\n    try {\n      final result = await FilePicker.platform.pickFiles(type: FileType.custom, allowedExtensions: ['json']);\n      if (result == null) return false;\n      final file = File(result.files.single.path!);\n      if (!await file.exists()) return false;\n      final bytes = await file.readAsBytes();\n      await _importJson(utf8.decode(bytes));\n      ref.read(inAppNotificationControllerProvider).showSuccessToast(t.common.msg.import.success);\n      return true;\n    } catch (e, st) {\n      loggy.warning(\"error importing config options from json file\", e, st);\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.common.msg.import.failure);\n      return false;\n    }\n  }\n\n  Future<void> resetOption() async {\n    for (final option in ConfigOptions.preferences.values) {\n      await ref.read(option.notifier).reset();\n    }\n    ref.invalidateSelf();\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/notifier/reset_tunnel/reset_tunnel_notifier.dart",
    "content": "import 'package:hiddify/hiddifycore/hiddify_core_service_provider.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'reset_tunnel_notifier.g.dart';\n\n@riverpod\nclass ResetTunnelNotifier extends _$ResetTunnelNotifier with AppLogger {\n  @override\n  Future<void> build() async {}\n\n  Future<void> run() async {\n    state = const AsyncLoading();\n    state = await AsyncValue.guard(\n      () => ref.read(hiddifyCoreServiceProvider).resetTunnel().getOrElse((err) {\n        loggy.warning(\"error resetting tunnel\", err);\n        throw err;\n      }).run(),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/notifier/warp_option/warp_option_notifier.dart",
    "content": "import 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/preferences/preferences_provider.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/model/config_option_failure.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service_provider.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:loggy/loggy.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\npart 'warp_option_notifier.g.dart';\n\n@riverpod\nclass WarpOptionNotifier extends _$WarpOptionNotifier with AppLogger {\n  SharedPreferences get _prefs => ref.read(sharedPreferencesProvider).requireValue;\n\n  @override\n  AsyncValue<String> build() {\n    bool hasWarpConfig = false;\n    try {\n      final accountId = _prefs.getString(WarpConst.warpAccountId);\n      final accessToken = _prefs.getString(WarpConst.warpAccessToken);\n      hasWarpConfig = accountId != null && accessToken != null;\n    } catch (e) {\n      loggy.warning(e);\n    }\n\n    return hasWarpConfig ? const AsyncValue.data(\"\") : AsyncError(const MissingWarpConfigFailure(), StackTrace.current);\n  }\n\n  Future<void> genWarps({bool showToast = true}) async {\n    if (state is AsyncLoading) return;\n    state = const AsyncLoading();\n    final t = ref.read(translationsProvider).requireValue;\n    final warpLog = await _genWarpConfig();\n    final warpLog2 = await _genWarp2Config();\n    if (warpLog != null && warpLog2 != null) {\n      loggy.log(LogLevel.info, 'generated warp log : $warpLog');\n      loggy.log(LogLevel.info, 'generated warp2 log : $warpLog2');\n      if (showToast) {\n        ref\n            .read(inAppNotificationControllerProvider)\n            .showSuccessToast('${t.pages.settings.warp.configGenerated} $warpLog');\n      }\n      state = AsyncValue.data(warpLog);\n    } else {\n      ref.read(inAppNotificationControllerProvider).showErrorToast(t.pages.settings.warp.missingConfig);\n      state = AsyncError(const MissingWarpConfigFailure(), StackTrace.current);\n    }\n  }\n\n  Future<String?> _genWarpConfig() async {\n    final result = await AsyncValue.guard(() async {\n      final warp = await ref\n          .read(hiddifyCoreServiceProvider)\n          .generateWarpConfig(\n            licenseKey: ref.read(ConfigOptions.warpLicenseKey),\n            previousAccountId: ref.read(ConfigOptions.warpAccountId),\n            previousAccessToken: ref.read(ConfigOptions.warpAccessToken),\n          )\n          .getOrElse((l) => throw l)\n          .run();\n\n      await ref.read(ConfigOptions.warpAccountId.notifier).update(warp.accountId);\n      await ref.read(ConfigOptions.warpAccessToken.notifier).update(warp.accessToken);\n      await ref.read(ConfigOptions.warpWireguardConfig.notifier).update(warp.wireguardConfig);\n      return warp.log;\n    });\n\n    state = result;\n    return result.value;\n  }\n\n  Future<String?> _genWarp2Config() async {\n    final result = await AsyncValue.guard(() async {\n      final warp = await ref\n          .read(hiddifyCoreServiceProvider)\n          .generateWarpConfig(\n            licenseKey: ref.read(ConfigOptions.warpLicenseKey),\n            previousAccountId: ref.read(ConfigOptions.warp2AccountId),\n            previousAccessToken: ref.read(ConfigOptions.warp2AccessToken),\n          )\n          .getOrElse((l) => throw l)\n          .run();\n\n      await ref.read(ConfigOptions.warp2AccountId.notifier).update(warp.accountId);\n      await ref.read(ConfigOptions.warp2AccessToken.notifier).update(warp.accessToken);\n      await ref.read(ConfigOptions.warp2WireguardConfig.notifier).update(warp.wireguardConfig);\n      return warp.log;\n    });\n\n    return result.value;\n  }\n}\n\n@riverpod\nclass WarpLicenseNotifier extends _$WarpLicenseNotifier with AppLogger {\n  SharedPreferences get _prefs => ref.read(sharedPreferencesProvider).requireValue;\n\n  @override\n  bool build() {\n    final consent = _prefs.getBool(WarpConst.warpConsentGiven) ?? false;\n    return consent;\n  }\n\n  Future<void> agree() async {\n    await _prefs.setBool(WarpConst.warpConsentGiven, true);\n    await ref.read(warpOptionNotifierProvider.notifier).genWarps(showToast: false);\n    state = true;\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/overview/sections/dns_options_page.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/widget/preference_tile.dart';\nimport 'package:hiddify/singbox/model/singbox_config_enum.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass DnsOptionsPage extends HookConsumerWidget {\n  const DnsOptionsPage({super.key});\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    return Scaffold(\n      appBar: AppBar(title: Text(t.pages.settings.dns.title)),\n      body: ListView(\n        children: [\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.remoteDnsAddress),\n            icon: Icons.vpn_lock_rounded,\n            preferences: ref.watch(ConfigOptions.remoteDnsAddress.notifier),\n            title: t.pages.settings.dns.remoteDns,\n          ),\n          ChoicePreferenceWidget(\n            selected: ref.watch(ConfigOptions.remoteDnsDomainStrategy),\n            preferences: ref.watch(ConfigOptions.remoteDnsDomainStrategy.notifier),\n            choices: DomainStrategy.values,\n            title: t.pages.settings.dns.remoteDnsDomainStrategy,\n            icon: Icons.sync_alt_rounded,\n            presentChoice: (value) => value.present(t),\n          ),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.dns.enableFakeDns),\n            secondary: const Icon(Icons.private_connectivity_rounded),\n            value: ref.watch(ConfigOptions.enableFakeDns),\n            onChanged: ref.read(ConfigOptions.enableFakeDns.notifier).update,\n          ),\n          ValuePreferenceWidget(\n            title: t.pages.settings.dns.directDns,\n            icon: Icons.public_rounded,\n            value: ref.watch(ConfigOptions.directDnsAddress),\n            preferences: ref.watch(ConfigOptions.directDnsAddress.notifier),\n          ),\n          ChoicePreferenceWidget(\n            selected: ref.watch(ConfigOptions.directDnsDomainStrategy),\n            preferences: ref.watch(ConfigOptions.directDnsDomainStrategy.notifier),\n            choices: DomainStrategy.values,\n            title: t.pages.settings.dns.directDnsDomainStrategy,\n            icon: Icons.sync_alt_rounded,\n            presentChoice: (value) => value.present(t),\n          ),\n          // SwitchListTile.adaptive(\n          //   title: Text(t.pages.settings.dns.enableDnsRouting),\n          //   secondary: const Icon(Icons.private_connectivity_rounded),\n          //   value: ref.watch(ConfigOptions.enableDnsRouting),\n          //   onChanged: ref.read(ConfigOptions.enableDnsRouting.notifier).update,\n          // ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/overview/sections/general_page.dart",
    "content": "import 'package:dartx/dartx.dart';\nimport 'package:flutter/material.dart';\nimport 'package:hiddify/core/haptic/haptic_service.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/auto_start/notifier/auto_start_notifier.dart';\nimport 'package:hiddify/features/common/general_pref_tiles.dart';\nimport 'package:hiddify/features/log/model/log_level.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/widget/preference_tile.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:humanizer/humanizer.dart';\n\nclass GeneralPage extends HookConsumerWidget {\n  const GeneralPage({super.key});\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    return Scaffold(\n      appBar: AppBar(title: Text(t.pages.settings.general.title)),\n      body: ListView(\n        children: [\n          const LocalePrefTile(),\n          const ThemeModePrefTile(),\n          const EnableAnalyticsPrefTile(),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.general.autoIpCheck),\n            value: ref.watch(Preferences.autoCheckIp),\n            secondary: const Icon(Icons.flag_rounded),\n            onChanged: ref.read(Preferences.autoCheckIp.notifier).update,\n          ),\n          if (PlatformUtils.isAndroid) ...[\n            SwitchListTile.adaptive(\n              title: Text(t.pages.settings.general.dynamicNotification),\n              secondary: const Icon(Icons.speed_rounded),\n              value: ref.watch(Preferences.dynamicNotification),\n              onChanged: ref.read(Preferences.dynamicNotification.notifier).update,\n            ),\n            SwitchListTile.adaptive(\n              title: Text(t.pages.settings.general.hapticFeedback),\n              secondary: const Icon(Icons.vibration_rounded),\n              value: ref.watch(hapticServiceProvider),\n              onChanged: ref.read(hapticServiceProvider.notifier).updatePreference,\n            ),\n          ],\n          if (PlatformUtils.isDesktop) ...[\n            const ClosingPrefTile(),\n            SwitchListTile.adaptive(\n              title: Text(t.pages.settings.general.autoStart),\n              secondary: const Icon(Icons.auto_mode_rounded),\n              value: ref.watch(autoStartNotifierProvider).asData!.value,\n              onChanged: (value) async => value\n                  ? await ref.read(autoStartNotifierProvider.notifier).enable()\n                  : await ref.read(autoStartNotifierProvider.notifier).disable(),\n            ),\n            SwitchListTile.adaptive(\n              title: Text(t.pages.settings.general.silentStart),\n              secondary: const Icon(Icons.visibility_off_rounded),\n              value: ref.watch(Preferences.silentStart),\n              onChanged: ref.read(Preferences.silentStart.notifier).update,\n            ),\n          ],\n          if (PlatformUtils.isAndroid) const BatteryOptimizationWidget(),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.general.memoryLimit),\n            subtitle: Text(t.pages.settings.general.memoryLimitMsg),\n            secondary: const Icon(Icons.memory_rounded),\n            value: !ref.watch(Preferences.disableMemoryLimit),\n            onChanged: (value) async => await ref.read(Preferences.disableMemoryLimit.notifier).update(!value),\n          ),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.general.debugMode),\n            secondary: const Icon(Icons.bug_report_rounded),\n            value: ref.watch(debugModeNotifierProvider),\n            onChanged: (value) async {\n              if (value)\n                await ref\n                    .read(dialogNotifierProvider.notifier)\n                    .showOk(t.pages.settings.general.debugMode, t.pages.settings.general.debugModeMsg);\n              await ref.read(debugModeNotifierProvider.notifier).update(value);\n            },\n          ),\n          ChoicePreferenceWidget(\n            selected: ref.watch(ConfigOptions.logLevel),\n            preferences: ref.watch(ConfigOptions.logLevel.notifier),\n            choices: LogLevel.choices,\n            title: t.pages.settings.general.logLevel,\n            icon: Icons.description_rounded,\n            presentChoice: (value) => value.name.toUpperCase(),\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.connectionTestUrl),\n            preferences: ref.watch(ConfigOptions.connectionTestUrl.notifier),\n            title: t.pages.settings.general.connectionTestUrl,\n            icon: Icons.link_rounded,\n          ),\n          ListTile(\n            title: Text(t.pages.settings.general.urlTestInterval),\n            subtitle: Text(ref.watch(ConfigOptions.urlTestInterval).toApproximateTime(isRelativeToNow: false)),\n            leading: const Icon(Icons.timer_rounded),\n            onTap: () async => await ref\n                .read(dialogNotifierProvider.notifier)\n                .showSettingSlider(\n                  title: t.pages.settings.general.urlTestInterval,\n                  initialValue: ref.watch(ConfigOptions.urlTestInterval).inMinutes.coerceIn(0, 60).toDouble(),\n                  onReset: ref.read(ConfigOptions.urlTestInterval.notifier).reset,\n                  min: 1,\n                  max: 60,\n                  divisions: 60,\n                  labelGen: (value) => Duration(minutes: value.toInt()).toApproximateTime(isRelativeToNow: false),\n                )\n                .then((value) async {\n                  if (value == null) return;\n                  await ref.read(ConfigOptions.urlTestInterval.notifier).update(Duration(minutes: value.toInt()));\n                }),\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.clashApiPort),\n            preferences: ref.watch(ConfigOptions.clashApiPort.notifier),\n            title: t.pages.settings.general.clashApiPort,\n            icon: Icons.api_rounded,\n            validateInput: isPort,\n            digitsOnly: true,\n            inputToValue: int.tryParse,\n          ),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.general.useXrayCoreWhenPossible),\n            subtitle: Text(t.pages.settings.general.useXrayCoreWhenPossibleMsg),\n            secondary: const Icon(Icons.extension_rounded),\n            value: ref.watch(ConfigOptions.useXrayCoreWhenPossible),\n            onChanged: ref.read(ConfigOptions.useXrayCoreWhenPossible.notifier).update,\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/overview/sections/inbound_options_page.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/widget/preference_tile.dart';\nimport 'package:hiddify/singbox/model/singbox_config_enum.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:network_info_plus/network_info_plus.dart';\n\nclass InboundOptionsPage extends HookConsumerWidget {\n  const InboundOptionsPage({super.key});\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    return Scaffold(\n      appBar: AppBar(title: Text(t.pages.settings.inbound.title)),\n      body: ListView(\n        children: [\n          ChoicePreferenceWidget(\n            selected: ref.watch(ConfigOptions.serviceMode),\n            preferences: ref.watch(ConfigOptions.serviceMode.notifier),\n            choices: ServiceMode.choices,\n            title: t.pages.settings.inbound.serviceMode,\n            icon: Icons.tune_rounded,\n            presentChoice: (value) => value.present(t),\n          ),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.inbound.strictRoute),\n            secondary: const Icon(Icons.merge_rounded),\n            value: ref.watch(ConfigOptions.strictRoute),\n            onChanged: ref.read(ConfigOptions.strictRoute.notifier).update,\n          ),\n          ChoicePreferenceWidget(\n            selected: ref.watch(ConfigOptions.tunImplementation),\n            preferences: ref.watch(ConfigOptions.tunImplementation.notifier),\n            choices: TunImplementation.values,\n            title: t.pages.settings.inbound.tunImplementation,\n            icon: Icons.trip_origin_rounded,\n            presentChoice: (value) => value.name,\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.mixedPort),\n            preferences: ref.watch(ConfigOptions.mixedPort.notifier),\n            title: t.pages.settings.inbound.mixedPort,\n            icon: Icons.device_hub_rounded,\n            inputToValue: int.tryParse,\n            digitsOnly: true,\n            validateInput: isPort,\n          ),\n          if (PlatformUtils.isLinux)\n            ValuePreferenceWidget(\n              value: ref.watch(ConfigOptions.tproxyPort),\n              preferences: ref.watch(ConfigOptions.tproxyPort.notifier),\n              title: t.pages.settings.inbound.tproxyPort,\n              icon: Icons.device_hub_rounded,\n              inputToValue: int.tryParse,\n              digitsOnly: true,\n              validateInput: isPort,\n            ),\n          if (PlatformUtils.isLinux || PlatformUtils.isMacOS)\n            ValuePreferenceWidget(\n              value: ref.watch(ConfigOptions.redirectPort),\n              preferences: ref.watch(ConfigOptions.redirectPort.notifier),\n              title: t.pages.settings.inbound.redirectPort,\n              icon: Icons.device_hub_rounded,\n              inputToValue: int.tryParse,\n              digitsOnly: true,\n              validateInput: isPort,\n            ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.directPort),\n            preferences: ref.watch(ConfigOptions.directPort.notifier),\n            title: t.pages.settings.inbound.directPort,\n            icon: Icons.device_hub_rounded,\n            inputToValue: int.tryParse,\n            digitsOnly: true,\n            validateInput: isPort,\n          ),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.inbound.allowConnectionFromLan),\n            secondary: const Icon(Icons.share_rounded),\n            value: ref.watch(ConfigOptions.allowConnectionFromLan),\n            onChanged: (bool value) async {\n              await ref.read(ConfigOptions.allowConnectionFromLan.notifier).update(value);\n              if (value == true) {\n                final ip = await NetworkInfo().getWifiIP();\n                // final ipp = Networkinfo\n                if (ip == null) return;\n                final port = ref.read(ConfigOptions.mixedPort);\n                final link = '#profile-title: LAN only\\nsocks://$ip:$port#LAN only';\n                final message = 'socks://$ip:$port';\n                await ref.read(dialogNotifierProvider.notifier).showQrCode(link, message: message);\n              }\n            },\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/overview/sections/route_options_page.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/region.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/features/per_app_proxy/model/per_app_proxy_mode.dart';\nimport 'package:hiddify/features/per_app_proxy/overview/per_app_proxy_notifier.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/widget/preference_tile.dart';\nimport 'package:hiddify/singbox/model/singbox_config_enum.dart';\nimport 'package:hiddify/utils/platform_utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass RouteOptionsPage extends HookConsumerWidget {\n  const RouteOptionsPage({super.key});\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final perAppProxy = ref.watch(Preferences.perAppProxyMode).enabled;\n    return Scaffold(\n      appBar: AppBar(title: Text(t.pages.settings.routing.title)),\n      body: ListView(\n        children: [\n          if (PlatformUtils.isAndroid)\n            ListTile(\n              title: Text(t.pages.settings.routing.perAppProxy.title),\n              leading: const Icon(Icons.apps_rounded),\n              trailing: Switch(\n                value: perAppProxy,\n                onChanged: (value) async {\n                  final newMode = perAppProxy ? PerAppProxyMode.off : PerAppProxyMode.exclude;\n                  await ref.read(Preferences.perAppProxyMode.notifier).update(newMode);\n                  if (!perAppProxy && context.mounted) context.goNamed('perAppProxy');\n                },\n              ),\n              onTap: () async {\n                if (!perAppProxy) {\n                  await ref.read(Preferences.perAppProxyMode.notifier).update(PerAppProxyMode.exclude);\n                }\n                if (context.mounted) context.goNamed('perAppProxy');\n              },\n            ),\n          ChoicePreferenceWidget(\n            selected: ref.watch(ConfigOptions.region),\n            preferences: ref.watch(ConfigOptions.region.notifier),\n            choices: Region.values,\n            title: t.pages.settings.routing.region,\n            showFlag: true,\n            icon: Icons.place_rounded,\n            presentChoice: (value) => value.present(t),\n            onChanged: (val) async {\n              await ref.read(ConfigOptions.directDnsAddress.notifier).reset();\n              final autoRegion = ref.read(Preferences.autoAppsSelectionRegion);\n              final mode = ref.read(Preferences.perAppProxyMode).toAppProxy();\n              if (autoRegion != val &&\n                  autoRegion != null &&\n                  val != Region.other &&\n                  mode != null &&\n                  PlatformUtils.isAndroid) {\n                await ref\n                    .read(dialogNotifierProvider.notifier)\n                    .showOk(\n                      t.pages.settings.routing.perAppProxy.autoSelection.dialog.title,\n                      t.pages.settings.routing.perAppProxy.autoSelection.dialog.msg(region: val.name),\n                    );\n                await ref.read(PerAppProxyProvider(mode).notifier).clearAutoSelected();\n              }\n            },\n          ),\n          ChoicePreferenceWidget(\n            title: t.pages.settings.routing.balancerStrategy.title,\n            icon: Icons.balance_rounded,\n            selected: ref.watch(ConfigOptions.balancerStrategy),\n            preferences: ref.watch(ConfigOptions.balancerStrategy.notifier),\n            choices: BalancerStrategy.values,\n            presentChoice: (value) => value.present(t),\n          ),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.routing.blockAds),\n            secondary: const Icon(Icons.block_rounded),\n            value: ref.watch(ConfigOptions.blockAds),\n            onChanged: ref.read(ConfigOptions.blockAds.notifier).update,\n          ),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.routing.bypassLan),\n            secondary: const Icon(Icons.call_split_rounded),\n            value: ref.watch(ConfigOptions.bypassLan),\n            onChanged: ref.read(ConfigOptions.bypassLan.notifier).update,\n          ),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.routing.resolveDestination),\n            secondary: const Icon(Icons.security_rounded),\n            value: ref.watch(ConfigOptions.resolveDestination),\n            onChanged: ref.read(ConfigOptions.resolveDestination.notifier).update,\n          ),\n          ChoicePreferenceWidget(\n            selected: ref.watch(ConfigOptions.ipv6Mode),\n            preferences: ref.watch(ConfigOptions.ipv6Mode.notifier),\n            choices: IPv6Mode.values,\n            title: t.pages.settings.routing.ipv6Route,\n            icon: Icons.looks_6_rounded,\n            presentChoice: (value) => value.present(t),\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/overview/sections/tls_tricks_page.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/optional_range.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/widget/preference_tile.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass TlsTricksPage extends HookConsumerWidget {\n  const TlsTricksPage({super.key});\n\n  String _presentFragmentPackets(TranslationsEn t, String value) => switch (value) {\n    \"tlshello\" => t.pages.settings.tlsTricks.packetsTlsHello,\n    \"1-1\" => t.pages.settings.tlsTricks.packets1_1,\n    \"1-2\" => t.pages.settings.tlsTricks.packets1_2,\n    \"1-3\" => t.pages.settings.tlsTricks.packets1_3,\n    \"1-4\" => t.pages.settings.tlsTricks.packets1_4,\n    \"1-5\" => t.pages.settings.tlsTricks.packets1_5,\n    _ => value,\n  };\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final canChangeOption = ref.watch(ConfigOptions.enableTlsFragment);\n    return Scaffold(\n      appBar: AppBar(title: Text(t.pages.settings.tlsTricks.title)),\n      body: ListView(\n        children: [\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.tlsTricks.enable),\n            value: ref.watch(ConfigOptions.enableTlsFragment),\n            secondary: const Icon(Icons.content_cut_rounded),\n            onChanged: ref.read(ConfigOptions.enableTlsFragment.notifier).update,\n          ),\n          ChoicePreferenceWidget(\n            selected: ref.watch(ConfigOptions.fragmentPackets),\n            preferences: ref.watch(ConfigOptions.fragmentPackets.notifier),\n            choices: [\"tlshello\", \"1-1\", \"1-2\", \"1-3\", \"1-4\", \"1-5\"],\n            title: t.pages.settings.tlsTricks.packets,\n            icon: Icons.layers_rounded,\n            presentChoice: (value) => _presentFragmentPackets(t, value),\n            enabled: canChangeOption,\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.tlsFragmentSize),\n            preferences: ref.watch(ConfigOptions.tlsFragmentSize.notifier),\n            title: t.pages.settings.tlsTricks.size,\n            icon: Icons.straighten_rounded,\n            inputToValue: OptionalRange.tryParse,\n            presentValue: (value) => value.present(t),\n            formatInputValue: (value) => value.format(),\n            enabled: canChangeOption,\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.tlsFragmentSleep),\n            preferences: ref.watch(ConfigOptions.tlsFragmentSleep.notifier),\n            title: t.pages.settings.tlsTricks.sleep,\n            icon: Icons.snooze_rounded,\n            inputToValue: OptionalRange.tryParse,\n            presentValue: (value) => value.present(t),\n            formatInputValue: (value) => value.format(),\n            enabled: canChangeOption,\n          ),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.tlsTricks.mixedSniCase.enable),\n            value: ref.watch(ConfigOptions.enableTlsMixedSniCase),\n            secondary: const Icon(Icons.text_fields_rounded),\n            onChanged: canChangeOption ? ref.read(ConfigOptions.enableTlsMixedSniCase.notifier).update : null,\n          ),\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.tlsTricks.padding.enable),\n            value: ref.watch(ConfigOptions.enableTlsPadding),\n            secondary: const Icon(Icons.expand_rounded),\n            onChanged: canChangeOption ? ref.read(ConfigOptions.enableTlsPadding.notifier).update : null,\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.tlsPaddingSize),\n            preferences: ref.watch(ConfigOptions.tlsPaddingSize.notifier),\n            title: t.pages.settings.tlsTricks.padding.size,\n            icon: Icons.straighten_rounded,\n            inputToValue: OptionalRange.tryParse,\n            presentValue: (value) => value.format(),\n            formatInputValue: (value) => value.format(),\n            enabled: canChangeOption,\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/overview/sections/warp_options_page.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/optional_range.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/settings/notifier/warp_option/warp_option_notifier.dart';\nimport 'package:hiddify/features/settings/widget/preference_tile.dart';\nimport 'package:hiddify/singbox/model/singbox_config_enum.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass WarpOptionsPage extends HookConsumerWidget {\n  const WarpOptionsPage({super.key});\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    final theme = Theme.of(context);\n    final warpOptions = ref.watch(warpOptionNotifierProvider);\n    final isWarpEnabled = ref.watch(ConfigOptions.enableWarp);\n    return Scaffold(\n      appBar: AppBar(title: Text(t.pages.settings.warp.title)),\n      body: ListView(\n        children: [\n          SwitchListTile.adaptive(\n            title: Text(t.pages.settings.warp.enable),\n            value: isWarpEnabled,\n            secondary: const Icon(Icons.cloud_rounded),\n            onChanged: (value) async {\n              await ref.read(ConfigOptions.enableWarp.notifier).update(value);\n              if (value) await ref.read(warpOptionNotifierProvider.notifier).genWarps();\n            },\n          ),\n          ListTile(\n            title: Text(t.pages.settings.warp.generateConfig),\n            subtitle: !isWarpEnabled\n                ? null\n                : warpOptions.when(\n                    loading: () => null,\n                    data: (_) => null,\n                    error: (_, _) =>\n                        Text(t.pages.settings.warp.missingConfig, style: TextStyle(color: theme.colorScheme.error)),\n                  ),\n            trailing: warpOptions.isLoading\n                ? const SizedBox(width: 24, height: 24, child: CircularProgressIndicator())\n                : null,\n            leading: const Icon(Icons.build_rounded),\n            enabled: isWarpEnabled && !warpOptions.isLoading,\n            onTap: warpOptions.isLoading\n                ? null\n                : () async {\n                    await ref.read(warpOptionNotifierProvider.notifier).genWarps();\n                  },\n          ),\n          ChoicePreferenceWidget(\n            selected: ref.watch(ConfigOptions.warpDetourMode),\n            preferences: ref.watch(ConfigOptions.warpDetourMode.notifier),\n            enabled: isWarpEnabled,\n            choices: WarpDetourMode.values,\n            title: t.pages.settings.warp.detourMode,\n            icon: Icons.alt_route_rounded,\n            presentChoice: (value) => value.present(t),\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.warpLicenseKey),\n            preferences: ref.watch(ConfigOptions.warpLicenseKey.notifier),\n            enabled: isWarpEnabled,\n            title: t.pages.settings.warp.licenseKey,\n            icon: Icons.key_rounded,\n            presentValue: (value) => value.isEmpty ? t.common.notSet : value,\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.warpCleanIp),\n            preferences: ref.watch(ConfigOptions.warpCleanIp.notifier),\n            enabled: isWarpEnabled,\n            title: t.pages.settings.warp.cleanIp,\n            icon: Icons.auto_awesome_rounded,\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.warpPort),\n            preferences: ref.watch(ConfigOptions.warpPort.notifier),\n            enabled: isWarpEnabled,\n            title: t.pages.settings.warp.port,\n            icon: Icons.device_hub_rounded,\n            inputToValue: int.tryParse,\n            validateInput: isPort,\n            digitsOnly: true,\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.warpNoise),\n            preferences: ref.watch(ConfigOptions.warpNoise.notifier),\n            enabled: isWarpEnabled,\n            title: t.pages.settings.warp.noise.count,\n            icon: Icons.web_stories_rounded,\n            inputToValue: (input) => OptionalRange.tryParse(input, allowEmpty: true),\n            presentValue: (value) => value.present(t),\n            formatInputValue: (value) => value.format(),\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.warpNoiseMode),\n            preferences: ref.watch(ConfigOptions.warpNoiseMode.notifier),\n            enabled: isWarpEnabled,\n            title: t.pages.settings.warp.noise.mode,\n            icon: Icons.mode_standby_rounded,\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.warpNoiseSize),\n            preferences: ref.watch(ConfigOptions.warpNoiseSize.notifier),\n            enabled: isWarpEnabled,\n            title: t.pages.settings.warp.noise.size,\n            icon: Icons.settings_ethernet_rounded,\n            inputToValue: (input) => OptionalRange.tryParse(input, allowEmpty: true),\n            presentValue: (value) => value.present(t),\n            formatInputValue: (value) => value.format(),\n          ),\n          ValuePreferenceWidget(\n            value: ref.watch(ConfigOptions.warpNoiseDelay),\n            preferences: ref.watch(ConfigOptions.warpNoiseDelay.notifier),\n            enabled: isWarpEnabled,\n            title: t.pages.settings.warp.noise.delay,\n            icon: Icons.schedule_rounded,\n            inputToValue: (input) => OptionalRange.tryParse(input, allowEmpty: true),\n            presentValue: (value) => value.present(t),\n            formatInputValue: (value) => value.format(),\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/overview/settings_page.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:go_router/go_router.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/core/router/go_router/helper/active_breakpoint_notifier.dart';\nimport 'package:hiddify/features/settings/notifier/config_option/config_option_notifier.dart';\nimport 'package:hiddify/features/settings/notifier/reset_tunnel/reset_tunnel_notifier.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nenum ConfigOptionSection {\n  warp,\n  fragment;\n\n  static final _warpKey = GlobalKey(debugLabel: \"warp-section-key\");\n  static final _fragmentKey = GlobalKey(debugLabel: \"fragment-section-key\");\n\n  GlobalKey get key => switch (this) {\n    ConfigOptionSection.warp => _warpKey,\n    ConfigOptionSection.fragment => _fragmentKey,\n  };\n}\n\nclass SettingsPage extends HookConsumerWidget {\n  SettingsPage({super.key, String? section})\n    : section = section != null ? ConfigOptionSection.values.byName(section) : null;\n\n  final ConfigOptionSection? section;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n    // final scrollController = useScrollController();\n\n    // useMemoized(\n    //   () {\n    //     if (section != null) {\n    //       WidgetsBinding.instance.addPostFrameCallback(\n    //         (_) {\n    //           final box = section!.key.currentContext?.findRenderObject() as RenderBox?;\n\n    //           final offset = box?.localToGlobal(Offset.zero);\n    //           if (offset == null) return;\n    //           final height = scrollController.offset + offset.dy - MediaQueryData.fromView(View.of(context)).padding.top - kToolbarHeight;\n    //           scrollController.animateTo(\n    //             height,\n    //             duration: const Duration(milliseconds: 500),\n    //             curve: Curves.decelerate,\n    //           );\n    //         },\n    //       );\n    //     }\n    //   },\n    // );\n\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(t.pages.settings.title),\n        actions: [\n          MenuAnchor(\n            menuChildren: <Widget>[\n              SubmenuButton(\n                menuChildren: <Widget>[\n                  MenuItemButton(\n                    onPressed: () async => await ref\n                        .read(dialogNotifierProvider.notifier)\n                        .showConfirmation(\n                          title: t.common.msg.import.confirm,\n                          message: t.dialogs.confirmation.settings.import.msg,\n                        )\n                        .then((shouldImport) async {\n                          if (shouldImport) {\n                            await ref.read(configOptionNotifierProvider.notifier).importFromClipboard();\n                          }\n                        }),\n                    child: Text(t.pages.settings.options.import.clipboard),\n                  ),\n                  MenuItemButton(\n                    onPressed: () async => await ref\n                        .read(dialogNotifierProvider.notifier)\n                        .showConfirmation(\n                          title: t.common.msg.import.confirm,\n                          message: t.dialogs.confirmation.settings.import.msg,\n                        )\n                        .then((shouldImport) async {\n                          if (shouldImport) {\n                            await ref.read(configOptionNotifierProvider.notifier).importFromJsonFile();\n                          }\n                        }),\n                    child: Text(t.pages.settings.options.import.file),\n                  ),\n                ],\n                child: Text(t.common.import),\n              ),\n              SubmenuButton(\n                menuChildren: <Widget>[\n                  MenuItemButton(\n                    onPressed: () async => await ref.read(configOptionNotifierProvider.notifier).exportJsonClipboard(),\n                    child: Text(t.pages.settings.options.export.anonymousToClipboard),\n                  ),\n                  MenuItemButton(\n                    onPressed: () async => await ref.read(configOptionNotifierProvider.notifier).exportJsonFile(),\n                    child: Text(t.pages.settings.options.export.anonymousToFile),\n                  ),\n                  const PopupMenuDivider(),\n                  MenuItemButton(\n                    onPressed: () async => await ref\n                        .read(configOptionNotifierProvider.notifier)\n                        .exportJsonClipboard(excludePrivate: false),\n                    child: Text(t.pages.settings.options.export.allToClipboard),\n                  ),\n                  MenuItemButton(\n                    onPressed: () async =>\n                        await ref.read(configOptionNotifierProvider.notifier).exportJsonFile(excludePrivate: false),\n                    child: Text(t.pages.settings.options.export.allToFile),\n                  ),\n                ],\n                child: Text(t.common.export),\n              ),\n              const PopupMenuDivider(),\n              MenuItemButton(\n                child: Text(t.pages.settings.options.reset),\n                onPressed: () async => await ref.read(configOptionNotifierProvider.notifier).resetOption(),\n              ),\n            ],\n            builder: (context, controller, child) => IconButton(\n              onPressed: () {\n                if (controller.isOpen) {\n                  controller.close();\n                } else {\n                  controller.open();\n                }\n              },\n              icon: const Icon(Icons.more_vert_rounded),\n            ),\n          ),\n          const Gap(8),\n        ],\n      ),\n      body: ListView(\n        children: [\n          // TipCard(message: t.settings.experimentalMsg),\n          SettingsSection(\n            title: t.pages.settings.general.title,\n            icon: Icons.layers_rounded,\n            namedLocation: context.namedLocation('general'),\n          ),\n          SettingsSection(\n            title: t.pages.settings.routing.title,\n            icon: Icons.route_rounded,\n            namedLocation: context.namedLocation('routeOptions'),\n          ),\n          SettingsSection(\n            title: t.pages.settings.dns.title,\n            icon: Icons.dns_rounded,\n            namedLocation: context.namedLocation('dnsOptions'),\n          ),\n          SettingsSection(\n            title: t.pages.settings.inbound.title,\n            icon: Icons.input_rounded,\n            namedLocation: context.namedLocation('inboundOptions'),\n          ),\n          SettingsSection(\n            title: t.pages.settings.tlsTricks.title,\n            icon: Icons.content_cut_rounded,\n            namedLocation: context.namedLocation('tlsTricks'),\n          ),\n          SettingsSection(\n            title: t.pages.settings.warp.title,\n            icon: Icons.cloud_rounded,\n            namedLocation: context.namedLocation('warpOptions'),\n          ),\n          if (PlatformUtils.isIOS)\n            Material(\n              child: ListTile(\n                title: Text(t.pages.settings.resetTunnel),\n                leading: const Icon(Icons.autorenew_rounded),\n                onTap: () async {\n                  await ref.read(resetTunnelNotifierProvider.notifier).run();\n                },\n              ),\n            ),\n          if (Breakpoint(context).isMobile()) ...[\n            SettingsSection(\n              title: t.pages.logs.title,\n              icon: Icons.description_rounded,\n              namedLocation: context.namedLocation('logs'),\n            ),\n            SettingsSection(\n              title: t.pages.about.title,\n              icon: Icons.info_rounded,\n              namedLocation: context.namedLocation('about'),\n            ),\n          ],\n        ],\n      ),\n    );\n  }\n}\n\nclass SettingsSection extends HookConsumerWidget {\n  const SettingsSection({super.key, required this.title, required this.icon, required this.namedLocation});\n\n  final String title;\n  final IconData icon;\n  final String namedLocation;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    return ListTile(\n      leading: Icon(icon),\n      title: Text(title),\n      trailing: const Icon(Icons.chevron_right_rounded),\n      onTap: () => context.go(namedLocation),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/widget/autocomplete_field.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass AutocompleteField extends StatelessWidget {\n  const AutocompleteField({super.key, required this.initialValue, required this.options});\n  final List<String> options;\n  final String initialValue;\n\n  @override\n  Widget build(BuildContext context) {\n    return Autocomplete<String>(\n      initialValue: TextEditingValue(\n        text: initialValue,\n        selection: TextSelection(baseOffset: 0, extentOffset: initialValue.length), // Selects the entire text\n      ),\n      optionsBuilder: (TextEditingValue textEditingValue) {\n        // if (textEditingValue.text == '') {\n        //   return const Iterable<String>.empty();\n        // }\n        return options.where((String option) {\n          return option.contains(textEditingValue.text.toLowerCase());\n        });\n      },\n      onSelected: (String selection) {\n        //debugPrint('You just selected $selection');\n      },\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/settings/widget/preference_tile.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/core/utils/preferences_utils.dart';\nimport 'package:hiddify/features/settings/notifier/battery_optimization/battery_optimizations_notifier.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ValuePreferenceWidget<T> extends HookConsumerWidget {\n  const ValuePreferenceWidget({\n    super.key,\n    required this.value,\n    required this.preferences,\n    this.enabled = true,\n    required this.title,\n    this.presentValue,\n    this.formatInputValue,\n    this.validateInput,\n    this.inputToValue,\n    this.digitsOnly = false,\n    this.icon,\n  });\n\n  final T value;\n  final PreferencesNotifier<T, dynamic> preferences;\n  final bool enabled;\n  final String title;\n  final String Function(T value)? presentValue;\n  final String Function(T value)? formatInputValue;\n  final bool Function(String value)? validateInput;\n  final T? Function(String input)? inputToValue;\n  final bool digitsOnly;\n  final IconData? icon;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    return ListTile(\n      title: Text(title),\n      subtitle: Text(presentValue?.call(value) ?? value.toString()),\n      leading: icon != null ? Icon(icon) : null,\n      // material: (context, platform) => MaterialListTileData(\n      enabled: enabled,\n\n      // ),\n      onTap: () async {\n        final inputValue = await ref\n            .read(dialogNotifierProvider.notifier)\n            .showSettingInput(\n              title: title,\n              initialValue: value,\n              validator: validateInput,\n              valueFormatter: formatInputValue,\n              onReset: preferences.reset,\n              digitsOnly: digitsOnly,\n              mapTo: inputToValue,\n              possibleValues: preferences.possibleValues,\n            );\n        if (inputValue == null) {\n          return;\n        }\n        await preferences.update(inputValue);\n      },\n    );\n  }\n}\n\nclass ChoicePreferenceWidget<T> extends HookConsumerWidget {\n  const ChoicePreferenceWidget({\n    super.key,\n    required this.selected,\n    required this.preferences,\n    this.enabled = true,\n    required this.choices,\n    required this.title,\n    this.showFlag = false,\n    this.icon,\n    required this.presentChoice,\n    this.validateInput,\n    this.onChanged,\n  });\n\n  final T selected;\n  final PreferencesNotifier<T, dynamic> preferences;\n  final bool enabled;\n  final List<T> choices;\n  final String title;\n  final bool showFlag;\n  final IconData? icon;\n  final String Function(T value) presentChoice;\n  final bool Function(String value)? validateInput;\n  final ValueChanged<T>? onChanged;\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    return ListTile(\n      title: Text(title),\n      subtitle: Text(presentChoice(selected)),\n      leading: icon != null ? Icon(icon) : null,\n      enabled: enabled,\n      onTap: () async {\n        final selection = await ref\n            .read(dialogNotifierProvider.notifier)\n            .showSettingPicker<T>(\n              title: title,\n              showFlag: showFlag,\n              selected: selected,\n              options: choices,\n              getTitle: (e) => presentChoice(e),\n              onReset: preferences.reset,\n            );\n        if (selection == null) return;\n        final out = await preferences.update(selection);\n        onChanged?.call(selection);\n        return out;\n      },\n    );\n  }\n}\n\nclass BatteryOptimizationWidget extends HookConsumerWidget {\n  const BatteryOptimizationWidget({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    final isIgnoringBatteryOptimizations = ref.watch(batteryOptimizationNotifierProvider);\n\n    return isIgnoringBatteryOptimizations.when(\n      data: (isIgnored) => isIgnored\n          ? const SizedBox()\n          : ListTile(\n              title: Text(t.pages.settings.general.ignoreBatteryOptimizations),\n              subtitle: Text(t.pages.settings.general.ignoreBatteryOptimizationsMsg),\n              leading: const Icon(Icons.battery_saver_rounded),\n              onTap: () async {\n                await ref.read(batteryOptimizationNotifierProvider.notifier).requestToIgnore();\n              },\n            ),\n      error: (_, _) => const SizedBox(),\n      loading: () => const SizedBox(\n        height: 48,\n        child: Center(\n          child: Padding(padding: EdgeInsets.symmetric(horizontal: 12), child: LinearProgressIndicator()),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/shortcut/shortcut_wrapper.dart",
    "content": "import 'dart:io';\n\nimport 'package:flutter/foundation.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:hiddify/core/router/bottom_sheets/bottom_sheets_notifier.dart';\nimport 'package:hiddify/core/router/go_router/go_router_notifier.dart';\nimport 'package:hiddify/features/window/notifier/window_notifier.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ShortcutWrapper extends HookConsumerWidget {\n  const ShortcutWrapper(this.child, {super.key});\n\n  final Widget child;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    return Shortcuts(\n      shortcuts: {\n        // Android TV D-pad select support\n        LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),\n        if (!kIsWeb) ...{\n          if (Platform.isLinux) ...{\n            // quit app using Control+Q on Linux\n            const SingleActivator(LogicalKeyboardKey.keyQ, control: true): QuitAppIntent(),\n          },\n          if (Platform.isMacOS) ...{\n            // close window using Command+W on macOS\n            const SingleActivator(LogicalKeyboardKey.keyW, meta: true): CloseWindowIntent(),\n\n            // open settings using Command+, on macOS\n            const SingleActivator(LogicalKeyboardKey.comma, meta: true): OpenSettingsIntent(),\n          },\n        },\n        // try adding profile using Command+V and Control+V\n        const SingleActivator(LogicalKeyboardKey.keyV, meta: true): PasteIntent(),\n        const SingleActivator(LogicalKeyboardKey.keyV, control: true): PasteIntent(),\n      },\n      child: Actions(\n        actions: {\n          CloseWindowIntent: CallbackAction(\n            onInvoke: (_) async {\n              await ref.read(windowNotifierProvider.notifier).hide();\n              return null;\n            },\n          ),\n          QuitAppIntent: CallbackAction(\n            onInvoke: (_) async {\n              await ref.read(windowNotifierProvider.notifier).exit();\n              return null;\n            },\n          ),\n          OpenSettingsIntent: CallbackAction(\n            onInvoke: (_) {\n              if (rootNavKey.currentContext != null) {\n                // const SettingsRoute().go(rootNavigatorKey.currentContext!);\n              }\n              return null;\n            },\n          ),\n          PasteIntent: CallbackAction(\n            onInvoke: (_) async {\n              if (rootNavKey.currentContext != null) {\n                final captureResult = await Clipboard.getData(Clipboard.kTextPlain).then((value) => value?.text ?? '');\n                ref.read(bottomSheetsNotifierProvider.notifier).showAddProfile(url: captureResult);\n              }\n              return null;\n            },\n          ),\n        },\n        child: child,\n      ),\n    );\n  }\n}\n\nclass CloseWindowIntent extends Intent {}\n\nclass QuitAppIntent extends Intent {}\n\nclass OpenSettingsIntent extends Intent {}\n\nclass PasteIntent extends Intent {}\n"
  },
  {
    "path": "lib/features/stats/data/stats_data_providers.dart",
    "content": "import 'package:hiddify/features/stats/data/stats_repository.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service_provider.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'stats_data_providers.g.dart';\n\n@Riverpod(keepAlive: true)\nStatsRepository statsRepository(StatsRepositoryRef ref) {\n  return StatsRepositoryImpl(singbox: ref.watch(hiddifyCoreServiceProvider));\n}\n"
  },
  {
    "path": "lib/features/stats/data/stats_repository.dart",
    "content": "import 'package:fpdart/fpdart.dart';\nimport 'package:hiddify/core/utils/exception_handler.dart';\nimport 'package:hiddify/features/stats/model/stats_failure.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\n\nabstract interface class StatsRepository {\n  Stream<Either<StatsFailure, SystemInfo>> watchStats();\n}\n\nclass StatsRepositoryImpl with ExceptionHandler, InfraLogger implements StatsRepository {\n  StatsRepositoryImpl({required this.singbox});\n\n  final HiddifyCoreService singbox;\n\n  @override\n  Stream<Either<StatsFailure, SystemInfo>> watchStats() {\n    return singbox.watchStats().handleExceptions(StatsUnexpectedFailure.new);\n  }\n}\n"
  },
  {
    "path": "lib/features/stats/model/stats_entity.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\n\npart 'stats_entity.freezed.dart';\n\n@freezed\nclass StatsEntity with _$StatsEntity {\n  const StatsEntity._();\n\n  const factory StatsEntity({\n    required int uplink,\n    required int downlink,\n    required int uplinkTotal,\n    required int downlinkTotal,\n  }) = _StatsEntity;\n\n  factory StatsEntity.empty() => const StatsEntity(uplink: 0, downlink: 0, uplinkTotal: 0, downlinkTotal: 0);\n}\n"
  },
  {
    "path": "lib/features/stats/model/stats_failure.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/failures.dart';\n\npart 'stats_failure.freezed.dart';\n\n@freezed\nsealed class StatsFailure with _$StatsFailure, Failure {\n  const StatsFailure._();\n\n  @With<UnexpectedFailure>()\n  const factory StatsFailure.unexpected([Object? error, StackTrace? stackTrace]) = StatsUnexpectedFailure;\n\n  @override\n  ({String type, String? message}) present(TranslationsEn t) {\n    return switch (this) {\n      StatsUnexpectedFailure() => (type: t.errors.unexpected, message: null),\n    };\n  }\n}\n"
  },
  {
    "path": "lib/features/stats/notifier/stats_notifier.dart",
    "content": "import 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/features/stats/data/stats_data_providers.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hiddify/utils/riverpod_utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'stats_notifier.g.dart';\n\n@riverpod\nclass StatsNotifier extends _$StatsNotifier with AppLogger {\n  @override\n  Stream<SystemInfo> build() async* {\n    ref.disposeDelay(const Duration(seconds: 10));\n    final serviceRunning = await ref.watch(serviceRunningProvider.future);\n    if (serviceRunning) {\n      yield* ref\n          .watch(statsRepositoryProvider)\n          .watchStats()\n          .map((event) => event.getOrElse((_) => SystemInfo.create()));\n    } else {\n      yield* Stream.value(SystemInfo.create());\n    }\n  }\n}\n"
  },
  {
    "path": "lib/features/stats/widget/connection_stats_card.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/widget/shimmer_skeleton.dart';\nimport 'package:hiddify/features/proxy/active/active_proxy_notifier.dart';\nimport 'package:hiddify/features/proxy/active/ip_widget.dart';\nimport 'package:hiddify/features/stats/widget/stats_card.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass ConnectionStatsCard extends HookConsumerWidget {\n  const ConnectionStatsCard({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    final activeProxy = ref.watch(activeProxyNotifierProvider);\n    // final ipInfo = ref.watch(ipInfoNotifierProvider);\n\n    return StatsCard(\n      title: t.components.stats.connection,\n      stats: [\n        switch (activeProxy) {\n          AsyncData(value: final proxy) => (\n            label: const Icon(FluentIcons.arrow_routing_20_regular),\n            data: Text(proxy.tagDisplay),\n            semanticLabel: null,\n          ),\n          _ => (label: const Icon(FluentIcons.arrow_routing_20_regular), data: const Text(\"...\"), semanticLabel: null),\n        },\n        switch (activeProxy) {\n          AsyncData(value: final proxy) when proxy.ipinfo.ip.isNotEmpty => (\n            label: Row(\n              children: [\n                IPCountryFlag(countryCode: proxy.ipinfo.countryCode, size: 16),\n                // const Gap(4),\n                // OrganisationFlag(organization: proxy.ipinfo.org, size: 16),\n              ],\n            ),\n            data: IPText(\n              ip: proxy.ipinfo.ip,\n              onLongPress: () async {\n                ref.read(ipInfoNotifierProvider.notifier).refresh();\n              },\n              constrained: true,\n            ),\n            semanticLabel: null,\n          ),\n          _ => (\n            label: const Icon(FluentIcons.question_circle_20_regular),\n            data: const ShimmerSkeleton(widthFactor: .85, height: 14),\n            semanticLabel: null,\n          ),\n        },\n        // switch (ipInfo) {\n        //   AsyncData(value: final info) => (\n        //       label: Row(\n        //         children: [\n        //           IPCountryFlag(\n        //             countryCode: info.countryCode,\n        //             size: 16,\n        //           ),\n        //           const Gap(4),\n        //           OrganisationFlag(organization: info.org ?? \"\", size: 16),\n        //         ],\n        //       ),\n        //       data: IPText(\n        //         ip: info.ip,\n        //         onLongPress: () async {\n        //           ref.read(ipInfoNotifierProvider.notifier).refresh();\n        //         },\n        //         constrained: true,\n        //       ),\n        //       semanticLabel: null,\n        //     ),\n        //   AsyncLoading() => (\n        //       label: const Icon(FluentIcons.question_circle_20_regular),\n        //       data: const ShimmerSkeleton(widthFactor: .85, height: 14),\n        //       semanticLabel: null,\n        //     ),\n        //   AsyncError(error: final UnknownIp _) => (\n        //       label: const Icon(FluentIcons.arrow_sync_20_regular),\n        //       data: UnknownIPText(\n        //         text: t.proxies.checkIp,\n        //         onTap: () async {\n        //           ref.read(ipInfoNotifierProvider.notifier).refresh();\n        //         },\n        //         constrained: true,\n        //       ),\n        //       semanticLabel: null,\n        //     ),\n        //   _ => (\n        //       label: const Icon(FluentIcons.error_circle_20_regular),\n        //       data: UnknownIPText(\n        //         text: t.proxies.unknownIp,\n        //         onTap: () async {\n        //           ref.read(ipInfoNotifierProvider.notifier).refresh();\n        //         },\n        //         constrained: true,\n        //       ),\n        //       semanticLabel: null,\n        //     ),\n        // },\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/stats/widget/side_bar_stats_overview.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/core/utils/preferences_utils.dart';\nimport 'package:hiddify/core/widget/animated_text.dart';\nimport 'package:hiddify/features/stats/notifier/stats_notifier.dart';\nimport 'package:hiddify/features/stats/widget/stats_card.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/utils/number_formatters.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nfinal showAllSidebarStatsProvider = PreferencesNotifier.createAutoDispose(\"show_all_sidebar_stats\", false);\n\nclass SideBarStatsOverview extends HookConsumerWidget {\n  const SideBarStatsOverview({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final t = ref.watch(translationsProvider).requireValue;\n\n    final stats = ref.watch(statsNotifierProvider).asData?.value ?? SystemInfo.create();\n    final showAll = ref.watch(showAllSidebarStatsProvider);\n\n    return Padding(\n      padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16),\n      child: Column(\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          Padding(\n            padding: const EdgeInsets.all(2.0),\n            child: TextButton.icon(\n              style: TextButton.styleFrom(\n                padding: const EdgeInsets.symmetric(horizontal: 8),\n                textStyle: Theme.of(context).textTheme.labelSmall,\n              ),\n              onPressed: () {\n                ref.read(showAllSidebarStatsProvider.notifier).update(!showAll);\n              },\n              icon: AnimatedRotation(\n                turns: showAll ? 1 : 0.5,\n                duration: kAnimationDuration,\n                child: const Icon(FluentIcons.chevron_down_16_regular, size: 16),\n              ),\n              label: AnimatedText(showAll ? t.common.showLess : t.common.showMore),\n            ),\n          ),\n          // const ConnectionStatsCard(),\n          const Gap(8),\n          AnimatedCrossFade(\n            crossFadeState: showAll ? CrossFadeState.showSecond : CrossFadeState.showFirst,\n            duration: kAnimationDuration,\n            firstChild: StatsCard(\n              title: t.components.stats.traffic,\n              stats: [\n                (\n                  label: const Icon(FluentIcons.arrow_download_16_regular),\n                  data: Text(stats.downlink.toInt().speed()),\n                  semanticLabel: t.components.stats.speed,\n                ),\n                (\n                  label: const Icon(FluentIcons.arrow_bidirectional_up_down_16_regular),\n                  data: Text(stats.downlinkTotal.toInt().size()),\n                  semanticLabel: t.components.stats.totalTransferred,\n                ),\n              ],\n            ),\n            secondChild: Column(\n              mainAxisSize: MainAxisSize.min,\n              children: [\n                StatsCard(\n                  title: t.components.stats.trafficLive,\n                  stats: [\n                    (\n                      label: const Text(\"↑\", style: TextStyle(color: Colors.green)),\n                      data: Text(stats.uplink.toInt().speed()),\n                      semanticLabel: t.components.stats.uplink,\n                    ),\n                    (\n                      label: Text(\"↓\", style: TextStyle(color: Theme.of(context).colorScheme.error)),\n                      data: Text(stats.downlink.toInt().speed()),\n                      semanticLabel: t.components.stats.downlink,\n                    ),\n                  ],\n                ),\n                const Gap(8),\n                StatsCard(\n                  title: t.components.stats.trafficTotal,\n                  stats: [\n                    (\n                      label: const Text(\"↑\", style: TextStyle(color: Colors.green)),\n                      data: Text(stats.uplinkTotal.toInt().size()),\n                      semanticLabel: t.components.stats.uplink,\n                    ),\n                    (\n                      label: Text(\"↓\", style: TextStyle(color: Theme.of(context).colorScheme.error)),\n                      data: Text(stats.downlinkTotal.toInt().size()),\n                      semanticLabel: t.components.stats.downlink,\n                    ),\n                  ],\n                ),\n              ],\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/stats/widget/stats_card.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hiddify/core/widget/spaced_list_widget.dart';\n\ntypedef PresentableStat = ({Widget label, Widget data, String? semanticLabel});\n\nclass StatsCard extends StatelessWidget {\n  const StatsCard({\n    super.key,\n    this.title,\n    this.titleStyle,\n    this.padding = const EdgeInsets.symmetric(vertical: 4, horizontal: 8),\n    this.labelStyle,\n    this.dataStyle,\n    required this.stats,\n  });\n\n  final String? title;\n  final TextStyle? titleStyle;\n  final EdgeInsets padding;\n  final TextStyle? labelStyle;\n  final TextStyle? dataStyle;\n  final List<PresentableStat> stats;\n\n  @override\n  Widget build(BuildContext context) {\n    final effectiveTitleStyle = titleStyle ?? Theme.of(context).textTheme.bodySmall;\n    final effectiveLabelStyle =\n        labelStyle ?? Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w300);\n    final effectiveDataStyle =\n        dataStyle ?? Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w300);\n\n    return Card(\n      margin: EdgeInsets.zero,\n      shadowColor: Colors.transparent,\n      child: Padding(\n        padding: padding,\n        child: Column(\n          mainAxisSize: MainAxisSize.min,\n          crossAxisAlignment: CrossAxisAlignment.start,\n          children: [\n            if (title != null) ...[Text(title!, style: effectiveTitleStyle), const Gap(4)],\n            ...stats\n                .map((stat) {\n                  Widget label = IconTheme.merge(\n                    data: const IconThemeData(size: 14),\n                    child: DefaultTextStyle(\n                      style: effectiveLabelStyle!,\n                      overflow: TextOverflow.ellipsis,\n                      child: stat.label,\n                    ),\n                  );\n                  if (stat.semanticLabel != null) {\n                    label = Tooltip(message: stat.semanticLabel, verticalOffset: 8, child: label);\n                  }\n                  return Row(\n                    mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                    children: [\n                      label,\n                      const Gap(2),\n                      DefaultTextStyle(style: effectiveDataStyle!, overflow: TextOverflow.ellipsis, child: stat.data),\n                    ],\n                  );\n                })\n                .toList()\n                .spaceBy(height: 2),\n          ],\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/features/system_tray/notifier/system_tray_notifier.dart",
    "content": "import 'dart:io';\n\nimport 'package:flutter/material.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/core/model/constants.dart';\nimport 'package:hiddify/features/connection/model/connection_status.dart';\nimport 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/features/proxy/active/active_proxy_notifier.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/features/window/notifier/window_notifier.dart';\nimport 'package:hiddify/gen/assets.gen.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/singbox/model/singbox_config_enum.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:tray_manager/tray_manager.dart';\nimport 'package:window_manager/window_manager.dart';\n\npart 'system_tray_notifier.g.dart';\n\n@Riverpod(keepAlive: true)\nclass SystemTrayNotifier extends _$SystemTrayNotifier with TrayListener, AppLogger {\n  bool listenerAdded = false;\n  @override\n  Future<void> build() async {\n    assert(PlatformUtils.isDesktop);\n    if (!listenerAdded) {\n      trayManager.addListener(this);\n      listenerAdded = true;\n    }\n    await _initializeTray();\n  }\n\n  Future<void> _initializeTray() async {\n    final t = await ref.watch(translationsProvider.future);\n    final urlTestDelay = await ref\n        .watch(activeProxyNotifierProvider.future)\n        .catchError((e) {\n          loggy.warning(\"error getting active proxy\", e);\n          return OutboundInfo(urlTestDelay: 0);\n        })\n        .then((connection) => connection.urlTestDelay);\n    final connection = await ref\n        .watch(connectionNotifierProvider.future)\n        .catchError((e) {\n          loggy.warning(\"error getting connection status\", e);\n          return const ConnectionStatus.disconnected();\n        })\n        .then((connection) => _modifyConnectionStatus(connection, urlTestDelay));\n    final serviceMode = ref.watch(ConfigOptions.serviceMode);\n\n    await trayManager.setIcon(_trayIconPath(connection), isTemplate: PlatformUtils.isMacOS);\n    if (!PlatformUtils.isLinux) await trayManager.setToolTip(_trayTooltip(connection, urlTestDelay, t));\n    await trayManager.setContextMenu(_trayMenu(connection, serviceMode, t));\n  }\n\n  Menu _trayMenu(ConnectionStatus connection, ServiceMode serviceMode, Translations t) => Menu(\n    items: [\n      if (PlatformUtils.isLinux) ...[MenuItem(key: 'dashboard', label: t.common.dashboard), MenuItem.separator()],\n      MenuItem(\n        key: 'connection',\n        label: switch (connection) {\n          Disconnected() => t.connection.connect,\n          Connecting() => t.connection.connecting,\n          Connected() => t.connection.disconnect,\n          Disconnecting() => t.connection.disconnecting,\n        },\n        disabled: connection.isSwitching,\n      ),\n      MenuItem.submenu(\n        label: t.pages.settings.inbound.serviceMode,\n        icon: Assets.images.trayIconIco,\n        submenu: Menu(\n          items: [\n            ...ServiceMode.values.map(\n              (e) => MenuItem.checkbox(checked: e == serviceMode, key: e.name, label: e.present(t)),\n            ),\n          ],\n        ),\n      ),\n      MenuItem.separator(),\n      MenuItem(key: 'quit', label: t.common.quit),\n    ],\n  );\n\n  String _trayIconPath(ConnectionStatus status) {\n    final isDarkMode = WidgetsBinding.instance.platformDispatcher.platformBrightness == Brightness.dark;\n    const images = Assets.images;\n    final isWindows = PlatformUtils.isWindows;\n    switch (status) {\n      case Connected():\n        return isWindows ? images.trayIconConnectedIco : images.trayIconConnectedPng.path;\n      case Connecting():\n      case Disconnecting():\n        return isWindows ? images.trayIconDisconnectedIco : images.trayIconDisconnectedPng.path;\n      case Disconnected():\n        return isWindows\n            ? isDarkMode\n                  ? images.trayIconIco\n                  : images.trayIconDarkIco\n            : isDarkMode\n            ? images.trayIconDarkPng.path\n            : images.trayIconPng.path;\n    }\n  }\n\n  String _trayTooltip(ConnectionStatus connection, int urlTestDelay, Translations t) {\n    final r = \"${Constants.appName} - ${connection.present(t)}\";\n    if (connection is Connected) {\n      if (Platform.isMacOS) windowManager.setBadgeLabel(\"${urlTestDelay}ms\");\n      return '$r : ${urlTestDelay}ms\"';\n    } else {\n      if (Platform.isMacOS) windowManager.setBadgeLabel(\"-ms\");\n      return r;\n    }\n  }\n\n  ConnectionStatus _modifyConnectionStatus(ConnectionStatus connection, int urlTestDelay) {\n    if (connection is Connected) {\n      return urlTestDelay > 0 && urlTestDelay < 65000 ? const Connected() : const Connecting();\n    } else {\n      return connection;\n    }\n  }\n\n  @override\n  Future<void> onTrayMenuItemClick(MenuItem menuItem) async {\n    // if (menuItem.key == 'dashboard') {\n    //   await ref.read(windowNotifierProvider.notifier).open();\n    // }\n    if (menuItem.key == 'dashboard') {\n      await ref.read(windowNotifierProvider.notifier).show();\n    } else if (menuItem.key == 'connection') {\n      await ref.read(connectionNotifierProvider.notifier).toggleConnection();\n    } else if (menuItem.key == 'quit') {\n      await ref.read(windowNotifierProvider.notifier).exit();\n    } else {\n      final newMode = ServiceMode.values.byName(menuItem.key!);\n      loggy.debug(\"switching service mode: [$newMode]\");\n      await ref.read(ConfigOptions.serviceMode.notifier).update(newMode);\n    }\n  }\n\n  @override\n  Future<void> onTrayIconMouseDown() async {\n    // if (Platform.isMacOS) {\n    //   await trayManager.popUpContextMenu();\n    // } else {\n    //   await ref.read(windowNotifierProvider.notifier).hideOrShow();\n    // }\n    await ref.read(windowNotifierProvider.notifier).showOrHide();\n  }\n\n  @override\n  Future<void> onTrayIconRightMouseDown() async {\n    await trayManager.popUpContextMenu();\n  }\n}\n\n// @Riverpod(keepAlive: true)\n// class SystemTrayNotifier extends _$SystemTrayNotifier with AppLogger {\n//   @override\n//   Future<void> build() async {\n//     if (!PlatformUtils.isDesktop) return;\n\n//     final activeProxy = await ref.watch(activeProxyNotifierProvider.future);\n//     final delay = activeProxy.urlTestDelay;\n//     final newConnectionStatus = delay > 0 && delay < 65000;\n//     ConnectionStatus connection;\n//     try {\n//       connection = await ref.watch(connectionNotifierProvider.future);\n//     } catch (e) {\n//       loggy.warning(\"error getting connection status\", e);\n//       connection = const ConnectionStatus.disconnected();\n//     }\n\n//     final t = await ref.watch(translationsProvider.future);\n\n//     var tooltip = Constants.appName;\n//     final serviceMode = ref.watch(ConfigOptions.serviceMode);\n//     if (connection is Disconnected) {\n//       setIcon(connection);\n//     } else if (newConnectionStatus) {\n//       setIcon(const Connected());\n//       tooltip = \"$tooltip - ${connection.present(t)}\";\n//       if (newConnectionStatus) {\n//         tooltip = \"$tooltip : ${delay}ms\";\n//       } else {\n//         tooltip = \"$tooltip : -\";\n//       }\n//       // else if (delay>1000)\n//       //   SystemTrayNotifier.setIcon(timeout ? Disconnecting() : Connecting());\n//     } else {\n//       setIcon(const Disconnecting());\n//       tooltip = \"$tooltip - ${connection.present(t)}\";\n//     }\n//     if (Platform.isMacOS) {\n//       windowManager.setBadgeLabel(\"${delay}ms\");\n//     }\n//     if (!Platform.isLinux) await trayManager.setToolTip(tooltip);\n\n//     // final destinations = <(String label, String location)>[\n//     //   (t.home.pageTitle, const HomeRoute().location),\n//     //   (t.proxies.pageTitle, const ProfilesOverviewRoute().location),\n//     //   (t.logs.title, const LogsOverviewRoute().location),\n//     //   // (t.settings.pageTitle, const SettingsRoute().location),\n//     //   (t.about.pageTitle, const AboutRoute().location),\n//     // ];\n\n//     // loggy.debug('updating system tray');\n\n//     final menu = Menu(\n//       items: [\n//         MenuItem(\n//           label: t.tray.dashboard,\n//           onClick: (_) async {\n//             await ref.read(windowNotifierProvider.notifier).open();\n//           },\n//         ),\n//         MenuItem.separator(),\n//         MenuItem.checkbox(\n//           label: switch (connection) {\n//             Disconnected() => t.tray.status.connect,\n//             Connecting() => t.tray.status.connecting,\n//             Connected() => t.tray.status.disconnect,\n//             Disconnecting() => t.tray.status.disconnecting,\n//           },\n//           // checked: connection.isConnected,\n//           checked: false,\n//           disabled: connection.isSwitching,\n//           onClick: (_) async {\n//            await ref.read(connectionNotifierProvider.notifier).toggleConnection();\n//          },\n//        ),\n//         MenuItem.separator(),\n//         MenuItem(\n//           label: t.config.serviceMode,\n//           icon: Assets.images.trayIconIco,\n//           disabled: true,\n//         ),\n\n//         ...ServiceMode.values.map(\n//           (e) => MenuItem.checkbox(\n//             checked: e == serviceMode,\n//             key: e.name,\n//             label: e.present(t),\n//             onClick: (menuItem) async {\n//               final newMode = ServiceMode.values.byName(menuItem.key!);\n//               loggy.debug(\"switching service mode: [$newMode]\");\n//               await ref.read(ConfigOptions.serviceMode.notifier).update(newMode);\n//             },\n//           ),\n//         ),\n\n//         // MenuItem.submenu(\n//         //   label: t.tray.open,\n//         //   submenu: Menu(\n//         //     items: [\n//         //       ...destinations.map(\n//         //         (e) => MenuItem(\n//         //           label: e.$1,\n//         //           onClick: (_) async {\n//         //             await ref.read(windowNotifierProvider.notifier).open();\n//         //             ref.read(routerProvider).go(e.$2);\n//         //           },\n//         //         ),\n//         //       ),\n//         //     ],\n//         //   ),\n//         // ),\n//         MenuItem.separator(),\n//         MenuItem(\n//           label: t.tray.quit,\n//           onClick: (_) async {\n//             return ref.read(windowNotifierProvider.notifier).quit();\n//           },\n//         ),\n//       ],\n//     );\n\n//     await trayManager.setContextMenu(menu);\n//   }\n\n//   static void setIcon(ConnectionStatus status) {\n//     if (!PlatformUtils.isDesktop) return;\n//     trayManager\n//         .setIcon(\n//           _trayIconPath(status),\n//           isTemplate: Platform.isMacOS,\n//         )\n//         .asStream();\n//   }\n\n//   static String _trayIconPath(ConnectionStatus status) {\n//     if (Platform.isWindows) {\n//       final Brightness brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness;\n//       final isDarkMode = brightness == Brightness.dark;\n//       switch (status) {\n//         case Connected():\n//           return Assets.images.trayIconConnectedIco;\n//         case Connecting():\n//           return Assets.images.trayIconDisconnectedIco;\n//         case Disconnecting():\n//           return Assets.images.trayIconDisconnectedIco;\n//         case Disconnected():\n//           if (isDarkMode) {\n//             return Assets.images.trayIconIco;\n//           } else {\n//             return Assets.images.trayIconDarkIco;\n//           }\n//       }\n//     }\n//     // const isDarkMode = false;\n//     switch (status) {\n//       case Connected():\n//         return Assets.images.trayIconConnectedPng.path;\n//       case Connecting():\n//         return Assets.images.trayIconDisconnectedPng.path;\n//       case Disconnecting():\n//         return Assets.images.trayIconDisconnectedPng.path;\n//       case Disconnected():\n//         // if (isDarkMode) {\n//         //   return Assets.images.trayIconDarkPng.path;\n//         // } else {\n//         //   return Assets.images.trayIconPng.path;\n//         // }\n//         return Assets.images.trayIconPng.path;\n//     }\n//     // return Assets.images.trayIconPng.path;\n//   }\n// }\n"
  },
  {
    "path": "lib/features/system_tray/widget/system_tray_wrapper.dart",
    "content": "// class TrayWrapper extends StatefulHookConsumerWidget {\n//   const TrayWrapper(this.child, {super.key});\n\n//   final Widget child;\n\n//   @override\n//   ConsumerState<ConsumerStatefulWidget> createState() => _TrayWrapperState();\n// }\n\n// class _TrayWrapperState extends ConsumerState<TrayWrapper> with TrayListener, AppLogger {\n//   @override\n//   Widget build(BuildContext context) {\n//     ref.listen(systemTrayNotifierProvider, (_, __) {});\n\n//     return widget.child;\n//   }\n\n//   @override\n//   void initState() {\n//     super.initState();\n//     trayManager.addListener(this);\n//   }\n\n//   @override\n//   void dispose() {\n//     trayManager.removeListener(this);\n//     super.dispose();\n//   }\n\n//   @override\n//   Future<void> onTrayIconMouseDown() async {\n//     if (Platform.isMacOS) {\n//       await trayManager.popUpContextMenu();\n//     } else {\n//       await ref.read(windowNotifierProvider.notifier).open();\n//     }\n//   }\n\n//   @override\n//   Future<void> onTrayIconRightMouseDown() async {\n//     await trayManager.popUpContextMenu();\n//   }\n// }\n"
  },
  {
    "path": "lib/features/window/notifier/window_notifier.dart",
    "content": "import 'dart:io';\nimport 'dart:ui';\n\nimport 'package:flutter/material.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/features/connection/notifier/connection_notifier.dart';\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:screen_retriever/screen_retriever.dart';\nimport 'package:tray_manager/tray_manager.dart';\nimport 'package:window_manager/window_manager.dart';\n\npart 'window_notifier.g.dart';\n\nconst minimumWindowSize = Size(368, 568);\nconst defaultWindowSize = Size(868, 668);\n\n@Riverpod(keepAlive: true)\nclass WindowNotifier extends _$WindowNotifier with AppLogger {\n  @override\n  Future<void> build() async {\n    if (!PlatformUtils.isDesktop) return;\n\n    // if (Platform.isWindows) {\n    //   loggy.debug(\"ensuring single instance\");\n    //   await WindowsSingleInstance.ensureSingleInstance([], \"Hiddify\");\n    // }\n\n    await windowManager.ensureInitialized();\n    await initWindowState();\n  }\n\n  Future<void> saveWindowState() async {\n    if (await windowManager.isMaximized()) {\n      await ref.read(Preferences.windowMaximized.notifier).update(true);\n    } else {\n      final size = await windowManager.getSize();\n      final position = await windowManager.getPosition();\n\n      await ref.read(Preferences.windowMaximized.notifier).update(false);\n      await ref.read(Preferences.windowSize.notifier).update(size);\n      await ref.read(Preferences.windowPosition.notifier).update(position);\n    }\n  }\n\n  Future<void> initWindowState() async {\n    final isMaximized = ref.read(Preferences.windowMaximized);\n    loggy.debug(\"window state. maximized: $isMaximized\");\n    final size = ref.read(Preferences.windowSize);\n    loggy.debug(\"window state. size: $size\");\n    final position = ref.read(Preferences.windowPosition);\n    final isWindowVisible = position != null && await checkWindowVisivility(position, size);\n    loggy.debug(\"window state. position: ${isWindowVisible ? position : \"centered\"}\");\n    final silentStart = ref.read(Preferences.silentStart);\n    loggy.debug(\"window state. silent start: ${silentStart ? \"Enabled\" : \"Disabled\"}\");\n\n    await windowManager.waitUntilReadyToShow(\n      WindowOptions(size: size, center: !isWindowVisible, minimumSize: minimumWindowSize),\n    );\n    if (isWindowVisible) {\n      await windowManager.setPosition(position);\n      loggy.debug(\"restoring window to position: $position\");\n    } else {\n      loggy.debug(\"no previous position found, centering window\");\n    }\n    if (isMaximized) {\n      await windowManager.maximize();\n      loggy.debug(\"restoring window to maximized state\");\n    }\n    if (!silentStart) {\n      await ref.read(windowNotifierProvider.notifier).show(focus: false);\n      loggy.debug(\"showing app window on start\");\n    } else {\n      loggy.debug(\"silent start, remain hidden accessible via tray\");\n    }\n  }\n\n  Future<bool> checkWindowVisivility(Offset windowPos, Size windowSize, {double tolerance = 10.0}) async {\n    final Rect windowRect = windowPos & windowSize;\n\n    final displays = await screenRetriever.getAllDisplays();\n\n    for (final display in displays) {\n      if (display.visiblePosition == null || display.visibleSize == null) {\n        continue;\n      }\n      final Rect monitorRect = display.visiblePosition! & display.visibleSize!;\n      if (windowRect.left >= (monitorRect.left - tolerance) &&\n          windowRect.top >= (monitorRect.top - tolerance) &&\n          windowRect.right <= (monitorRect.right + tolerance) &&\n          windowRect.bottom <= (monitorRect.bottom + tolerance)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  Future<void> show({bool focus = true}) async {\n    await windowManager.show();\n    if (focus) await windowManager.focus();\n    if (Platform.isMacOS) {\n      await windowManager.setSkipTaskbar(false);\n    }\n  }\n\n  Future<void> hide() async {\n    await windowManager.hide();\n    if (Platform.isMacOS) {\n      await windowManager.setSkipTaskbar(true);\n    }\n  }\n\n  Future<void> showOrHide() async {\n    if (await windowManager.isVisible()) {\n      await hide();\n    } else {\n      await show();\n    }\n  }\n\n  Future<void> exit() async {\n    await ref\n        .read(connectionNotifierProvider.notifier)\n        .abortConnection()\n        .timeout(const Duration(seconds: 2))\n        .catchError((e) {\n          loggy.warning(\"error aborting connection on quit\", e);\n        });\n    await trayManager.destroy();\n    await windowManager.destroy();\n  }\n}\n"
  },
  {
    "path": "lib/features/window/widget/window_wrapper.dart",
    "content": "import 'dart:async';\n\nimport 'package:flutter/material.dart';\nimport 'package:hiddify/core/preferences/actions_at_closing.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/core/router/dialog/dialog_notifier.dart';\nimport 'package:hiddify/core/router/go_router/go_router_notifier.dart';\nimport 'package:hiddify/features/window/notifier/window_notifier.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hiddify/utils/platform_utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:window_manager/window_manager.dart';\n\nclass WindowWrapper extends StatefulHookConsumerWidget {\n  const WindowWrapper(this.child, {super.key});\n\n  final Widget child;\n\n  @override\n  ConsumerState<ConsumerStatefulWidget> createState() => _WindowWrapperState();\n}\n\nclass _WindowWrapperState extends ConsumerState<WindowWrapper> with WindowListener, AppLogger {\n  late AlertDialog closeDialog;\n\n  bool isWindowClosingDialogOpened = false;\n\n  @override\n  Widget build(BuildContext context) {\n    ref.watch(windowNotifierProvider);\n\n    return widget.child;\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    windowManager.addListener(this);\n    if (PlatformUtils.isDesktop) {\n      WidgetsBinding.instance.addPostFrameCallback((_) async {\n        await windowManager.setPreventClose(true);\n      });\n    }\n  }\n\n  @override\n  void dispose() {\n    windowManager.removeListener(this);\n    super.dispose();\n  }\n\n  @override\n  Future<void> onWindowClose() async {\n    if (rootNavKey.currentContext == null) {\n      await ref.read(windowNotifierProvider.notifier).hide();\n      return;\n    }\n\n    switch (ref.read(Preferences.actionAtClose)) {\n      case ActionsAtClosing.ask:\n        if (isWindowClosingDialogOpened) return;\n        isWindowClosingDialogOpened = true;\n        await ref.read(dialogNotifierProvider.notifier).showWindowClosing();\n        isWindowClosingDialogOpened = false;\n\n      case ActionsAtClosing.hide:\n        await ref.read(windowNotifierProvider.notifier).hide();\n\n      case ActionsAtClosing.exit:\n        await ref.read(windowNotifierProvider.notifier).exit();\n    }\n  }\n\n  @override\n  Future<void> onWindowResized() async {\n    await ref.read(windowNotifierProvider.notifier).saveWindowState();\n  }\n\n  @override\n  Future<void> onWindowMoved() async {\n    await ref.read(windowNotifierProvider.notifier).saveWindowState();\n  }\n\n  @override\n  Future<void> onWindowMaximize() async {\n    await ref.read(windowNotifierProvider.notifier).saveWindowState();\n  }\n\n  @override\n  Future<void> onWindowUnmaximize() async {\n    await ref.read(windowNotifierProvider.notifier).saveWindowState();\n  }\n\n  @override\n  void onWindowFocus() {\n    setState(() {});\n  }\n}\n"
  },
  {
    "path": "lib/gen/hiddify_core_generated_bindings.dart",
    "content": "// AUTO GENERATED FILE, DO NOT EDIT.\n//\n// Generated by `package:ffigen`.\n// ignore_for_file: type=lint\nimport 'dart:ffi' as ffi;\n\n/// Bindings to Hiddify Core Library\nclass HiddifyCoreNativeLibrary {\n  /// Holds the symbol lookup function.\n  final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) _lookup;\n\n  /// The symbols are looked up in [dynamicLibrary].\n  HiddifyCoreNativeLibrary(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup;\n\n  /// The symbols are looked up with [lookup].\n  HiddifyCoreNativeLibrary.fromLookup(ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) lookup)\n    : _lookup = lookup;\n\n  ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> signal(\n    int arg0,\n    ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> arg1,\n  ) {\n    return _signal(arg0, arg1);\n  }\n\n  late final _signalPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> Function(\n            ffi.Int,\n            ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>,\n          )\n        >\n      >('signal');\n  late final _signal = _signalPtr\n      .asFunction<\n        ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> Function(\n          int,\n          ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>,\n        )\n      >();\n\n  int getpriority(int arg0, int arg1) {\n    return _getpriority(arg0, arg1);\n  }\n\n  late final _getpriorityPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, id_t)>>('getpriority');\n  late final _getpriority = _getpriorityPtr.asFunction<int Function(int, int)>();\n\n  int getiopolicy_np(int arg0, int arg1) {\n    return _getiopolicy_np(arg0, arg1);\n  }\n\n  late final _getiopolicy_npPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Int)>>('getiopolicy_np');\n  late final _getiopolicy_np = _getiopolicy_npPtr.asFunction<int Function(int, int)>();\n\n  int getrlimit(int arg0, ffi.Pointer<rlimit> arg1) {\n    return _getrlimit(arg0, arg1);\n  }\n\n  late final _getrlimitPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Pointer<rlimit>)>>('getrlimit');\n  late final _getrlimit = _getrlimitPtr.asFunction<int Function(int, ffi.Pointer<rlimit>)>();\n\n  int getrusage(int arg0, ffi.Pointer<rusage> arg1) {\n    return _getrusage(arg0, arg1);\n  }\n\n  late final _getrusagePtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Pointer<rusage>)>>('getrusage');\n  late final _getrusage = _getrusagePtr.asFunction<int Function(int, ffi.Pointer<rusage>)>();\n\n  int setpriority(int arg0, int arg1, int arg2) {\n    return _setpriority(arg0, arg1, arg2);\n  }\n\n  late final _setpriorityPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, id_t, ffi.Int)>>('setpriority');\n  late final _setpriority = _setpriorityPtr.asFunction<int Function(int, int, int)>();\n\n  int setiopolicy_np(int arg0, int arg1, int arg2) {\n    return _setiopolicy_np(arg0, arg1, arg2);\n  }\n\n  late final _setiopolicy_npPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Int, ffi.Int)>>(\n    'setiopolicy_np',\n  );\n  late final _setiopolicy_np = _setiopolicy_npPtr.asFunction<int Function(int, int, int)>();\n\n  int setrlimit(int arg0, ffi.Pointer<rlimit> arg1) {\n    return _setrlimit(arg0, arg1);\n  }\n\n  late final _setrlimitPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Pointer<rlimit>)>>('setrlimit');\n  late final _setrlimit = _setrlimitPtr.asFunction<int Function(int, ffi.Pointer<rlimit>)>();\n\n  int wait1(ffi.Pointer<ffi.Int> arg0) {\n    return _wait1(arg0);\n  }\n\n  late final _wait1Ptr = _lookup<ffi.NativeFunction<pid_t Function(ffi.Pointer<ffi.Int>)>>('wait');\n  late final _wait1 = _wait1Ptr.asFunction<int Function(ffi.Pointer<ffi.Int>)>();\n\n  int waitpid(int arg0, ffi.Pointer<ffi.Int> arg1, int arg2) {\n    return _waitpid(arg0, arg1, arg2);\n  }\n\n  late final _waitpidPtr = _lookup<ffi.NativeFunction<pid_t Function(pid_t, ffi.Pointer<ffi.Int>, ffi.Int)>>('waitpid');\n  late final _waitpid = _waitpidPtr.asFunction<int Function(int, ffi.Pointer<ffi.Int>, int)>();\n\n  int waitid(idtype_t arg0, Dart__uint32_t arg1, ffi.Pointer<siginfo_t> arg2, int arg3) {\n    return _waitid(arg0.value, arg1, arg2, arg3);\n  }\n\n  late final _waitidPtr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.UnsignedInt, id_t, ffi.Pointer<siginfo_t>, ffi.Int)>>('waitid');\n  late final _waitid = _waitidPtr.asFunction<int Function(int, int, ffi.Pointer<siginfo_t>, int)>();\n\n  int wait3(ffi.Pointer<ffi.Int> arg0, int arg1, ffi.Pointer<rusage> arg2) {\n    return _wait3(arg0, arg1, arg2);\n  }\n\n  late final _wait3Ptr =\n      _lookup<ffi.NativeFunction<pid_t Function(ffi.Pointer<ffi.Int>, ffi.Int, ffi.Pointer<rusage>)>>('wait3');\n  late final _wait3 = _wait3Ptr.asFunction<int Function(ffi.Pointer<ffi.Int>, int, ffi.Pointer<rusage>)>();\n\n  int wait4(int arg0, ffi.Pointer<ffi.Int> arg1, int arg2, ffi.Pointer<rusage> arg3) {\n    return _wait4(arg0, arg1, arg2, arg3);\n  }\n\n  late final _wait4Ptr =\n      _lookup<ffi.NativeFunction<pid_t Function(pid_t, ffi.Pointer<ffi.Int>, ffi.Int, ffi.Pointer<rusage>)>>('wait4');\n  late final _wait4 = _wait4Ptr.asFunction<int Function(int, ffi.Pointer<ffi.Int>, int, ffi.Pointer<rusage>)>();\n\n  ffi.Pointer<ffi.Void> alloca(int arg0) {\n    return _alloca(arg0);\n  }\n\n  late final _allocaPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size)>>('alloca');\n  late final _alloca = _allocaPtr.asFunction<ffi.Pointer<ffi.Void> Function(int)>();\n\n  late final ffi.Pointer<ffi.Int> ___mb_cur_max = _lookup<ffi.Int>('__mb_cur_max');\n\n  int get __mb_cur_max => ___mb_cur_max.value;\n\n  set __mb_cur_max(int value) => ___mb_cur_max.value = value;\n\n  ffi.Pointer<ffi.Void> malloc_type_malloc(int size, int type_id) {\n    return _malloc_type_malloc(size, type_id);\n  }\n\n  late final _malloc_type_mallocPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size, malloc_type_id_t)>>('malloc_type_malloc');\n  late final _malloc_type_malloc = _malloc_type_mallocPtr.asFunction<ffi.Pointer<ffi.Void> Function(int, int)>();\n\n  ffi.Pointer<ffi.Void> malloc_type_calloc(int count, int size, int type_id) {\n    return _malloc_type_calloc(count, size, type_id);\n  }\n\n  late final _malloc_type_callocPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size, ffi.Size, malloc_type_id_t)>>(\n        'malloc_type_calloc',\n      );\n  late final _malloc_type_calloc = _malloc_type_callocPtr.asFunction<ffi.Pointer<ffi.Void> Function(int, int, int)>();\n\n  void malloc_type_free(ffi.Pointer<ffi.Void> ptr, int type_id) {\n    return _malloc_type_free(ptr, type_id);\n  }\n\n  late final _malloc_type_freePtr =\n      _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>, malloc_type_id_t)>>('malloc_type_free');\n  late final _malloc_type_free = _malloc_type_freePtr.asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();\n\n  ffi.Pointer<ffi.Void> malloc_type_realloc(ffi.Pointer<ffi.Void> ptr, int size, int type_id) {\n    return _malloc_type_realloc(ptr, size, type_id);\n  }\n\n  late final _malloc_type_reallocPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>, ffi.Size, malloc_type_id_t)>>(\n        'malloc_type_realloc',\n      );\n  late final _malloc_type_realloc = _malloc_type_reallocPtr\n      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>, int, int)>();\n\n  ffi.Pointer<ffi.Void> malloc_type_valloc(int size, int type_id) {\n    return _malloc_type_valloc(size, type_id);\n  }\n\n  late final _malloc_type_vallocPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size, malloc_type_id_t)>>('malloc_type_valloc');\n  late final _malloc_type_valloc = _malloc_type_vallocPtr.asFunction<ffi.Pointer<ffi.Void> Function(int, int)>();\n\n  ffi.Pointer<ffi.Void> malloc_type_aligned_alloc(int alignment, int size, int type_id) {\n    return _malloc_type_aligned_alloc(alignment, size, type_id);\n  }\n\n  late final _malloc_type_aligned_allocPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size, ffi.Size, malloc_type_id_t)>>(\n        'malloc_type_aligned_alloc',\n      );\n  late final _malloc_type_aligned_alloc = _malloc_type_aligned_allocPtr\n      .asFunction<ffi.Pointer<ffi.Void> Function(int, int, int)>();\n\n  int malloc_type_posix_memalign(ffi.Pointer<ffi.Pointer<ffi.Void>> memptr, int alignment, int size, int type_id) {\n    return _malloc_type_posix_memalign(memptr, alignment, size, type_id);\n  }\n\n  late final _malloc_type_posix_memalignPtr =\n      _lookup<\n        ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Pointer<ffi.Void>>, ffi.Size, ffi.Size, malloc_type_id_t)>\n      >('malloc_type_posix_memalign');\n  late final _malloc_type_posix_memalign = _malloc_type_posix_memalignPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Pointer<ffi.Void>>, int, int, int)>();\n\n  ffi.Pointer<ffi.Void> malloc_type_zone_malloc(ffi.Pointer<malloc_zone_t> zone, int size, int type_id) {\n    return _malloc_type_zone_malloc(zone, size, type_id);\n  }\n\n  late final _malloc_type_zone_mallocPtr =\n      _lookup<\n        ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<malloc_zone_t>, ffi.Size, malloc_type_id_t)>\n      >('malloc_type_zone_malloc');\n  late final _malloc_type_zone_malloc = _malloc_type_zone_mallocPtr\n      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<malloc_zone_t>, int, int)>();\n\n  ffi.Pointer<ffi.Void> malloc_type_zone_calloc(ffi.Pointer<malloc_zone_t> zone, int count, int size, int type_id) {\n    return _malloc_type_zone_calloc(zone, count, size, type_id);\n  }\n\n  late final _malloc_type_zone_callocPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Pointer<ffi.Void> Function(ffi.Pointer<malloc_zone_t>, ffi.Size, ffi.Size, malloc_type_id_t)\n        >\n      >('malloc_type_zone_calloc');\n  late final _malloc_type_zone_calloc = _malloc_type_zone_callocPtr\n      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<malloc_zone_t>, int, int, int)>();\n\n  void malloc_type_zone_free(ffi.Pointer<malloc_zone_t> zone, ffi.Pointer<ffi.Void> ptr, int type_id) {\n    return _malloc_type_zone_free(zone, ptr, type_id);\n  }\n\n  late final _malloc_type_zone_freePtr =\n      _lookup<\n        ffi.NativeFunction<ffi.Void Function(ffi.Pointer<malloc_zone_t>, ffi.Pointer<ffi.Void>, malloc_type_id_t)>\n      >('malloc_type_zone_free');\n  late final _malloc_type_zone_free = _malloc_type_zone_freePtr\n      .asFunction<void Function(ffi.Pointer<malloc_zone_t>, ffi.Pointer<ffi.Void>, int)>();\n\n  ffi.Pointer<ffi.Void> malloc_type_zone_realloc(\n    ffi.Pointer<malloc_zone_t> zone,\n    ffi.Pointer<ffi.Void> ptr,\n    int size,\n    int type_id,\n  ) {\n    return _malloc_type_zone_realloc(zone, ptr, size, type_id);\n  }\n\n  late final _malloc_type_zone_reallocPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Pointer<ffi.Void> Function(ffi.Pointer<malloc_zone_t>, ffi.Pointer<ffi.Void>, ffi.Size, malloc_type_id_t)\n        >\n      >('malloc_type_zone_realloc');\n  late final _malloc_type_zone_realloc = _malloc_type_zone_reallocPtr\n      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<malloc_zone_t>, ffi.Pointer<ffi.Void>, int, int)>();\n\n  ffi.Pointer<ffi.Void> malloc_type_zone_valloc(ffi.Pointer<malloc_zone_t> zone, int size, int type_id) {\n    return _malloc_type_zone_valloc(zone, size, type_id);\n  }\n\n  late final _malloc_type_zone_vallocPtr =\n      _lookup<\n        ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<malloc_zone_t>, ffi.Size, malloc_type_id_t)>\n      >('malloc_type_zone_valloc');\n  late final _malloc_type_zone_valloc = _malloc_type_zone_vallocPtr\n      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<malloc_zone_t>, int, int)>();\n\n  ffi.Pointer<ffi.Void> malloc_type_zone_memalign(\n    ffi.Pointer<malloc_zone_t> zone,\n    int alignment,\n    int size,\n    int type_id,\n  ) {\n    return _malloc_type_zone_memalign(zone, alignment, size, type_id);\n  }\n\n  late final _malloc_type_zone_memalignPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Pointer<ffi.Void> Function(ffi.Pointer<malloc_zone_t>, ffi.Size, ffi.Size, malloc_type_id_t)\n        >\n      >('malloc_type_zone_memalign');\n  late final _malloc_type_zone_memalign = _malloc_type_zone_memalignPtr\n      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<malloc_zone_t>, int, int, int)>();\n\n  ffi.Pointer<ffi.Void> malloc(int __size) {\n    return _malloc(__size);\n  }\n\n  late final _mallocPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size)>>('malloc');\n  late final _malloc = _mallocPtr.asFunction<ffi.Pointer<ffi.Void> Function(int)>();\n\n  ffi.Pointer<ffi.Void> calloc(int __count, int __size) {\n    return _calloc(__count, __size);\n  }\n\n  late final _callocPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size, ffi.Size)>>('calloc');\n  late final _calloc = _callocPtr.asFunction<ffi.Pointer<ffi.Void> Function(int, int)>();\n\n  void free(ffi.Pointer<ffi.Void> arg0) {\n    return _free(arg0);\n  }\n\n  late final _freePtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>('free');\n  late final _free = _freePtr.asFunction<void Function(ffi.Pointer<ffi.Void>)>();\n\n  ffi.Pointer<ffi.Void> realloc(ffi.Pointer<ffi.Void> __ptr, int __size) {\n    return _realloc(__ptr, __size);\n  }\n\n  late final _reallocPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>, ffi.Size)>>(\n    'realloc',\n  );\n  late final _realloc = _reallocPtr.asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>, int)>();\n\n  ffi.Pointer<ffi.Void> reallocf(ffi.Pointer<ffi.Void> __ptr, int __size) {\n    return _reallocf(__ptr, __size);\n  }\n\n  late final _reallocfPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>, ffi.Size)>>('reallocf');\n  late final _reallocf = _reallocfPtr.asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>, int)>();\n\n  ffi.Pointer<ffi.Void> valloc(int arg0) {\n    return _valloc(arg0);\n  }\n\n  late final _vallocPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size)>>('valloc');\n  late final _valloc = _vallocPtr.asFunction<ffi.Pointer<ffi.Void> Function(int)>();\n\n  ffi.Pointer<ffi.Void> aligned_alloc(int __alignment, int __size) {\n    return _aligned_alloc(__alignment, __size);\n  }\n\n  late final _aligned_allocPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size, ffi.Size)>>(\n    'aligned_alloc',\n  );\n  late final _aligned_alloc = _aligned_allocPtr.asFunction<ffi.Pointer<ffi.Void> Function(int, int)>();\n\n  int posix_memalign(ffi.Pointer<ffi.Pointer<ffi.Void>> __memptr, int __alignment, int __size) {\n    return _posix_memalign(__memptr, __alignment, __size);\n  }\n\n  late final _posix_memalignPtr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Pointer<ffi.Void>>, ffi.Size, ffi.Size)>>(\n        'posix_memalign',\n      );\n  late final _posix_memalign = _posix_memalignPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Pointer<ffi.Void>>, int, int)>();\n\n  void abort() {\n    return _abort();\n  }\n\n  late final _abortPtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('abort');\n  late final _abort = _abortPtr.asFunction<void Function()>();\n\n  int abs(int arg0) {\n    return _abs(arg0);\n  }\n\n  late final _absPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('abs');\n  late final _abs = _absPtr.asFunction<int Function(int)>();\n\n  int atexit(ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> arg0) {\n    return _atexit(arg0);\n  }\n\n  late final _atexitPtr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>>('atexit');\n  late final _atexit = _atexitPtr.asFunction<int Function(ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>();\n\n  double atof(ffi.Pointer<ffi.Char> arg0) {\n    return _atof(arg0);\n  }\n\n  late final _atofPtr = _lookup<ffi.NativeFunction<ffi.Double Function(ffi.Pointer<ffi.Char>)>>('atof');\n  late final _atof = _atofPtr.asFunction<double Function(ffi.Pointer<ffi.Char>)>();\n\n  int atoi(ffi.Pointer<ffi.Char> arg0) {\n    return _atoi(arg0);\n  }\n\n  late final _atoiPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>)>>('atoi');\n  late final _atoi = _atoiPtr.asFunction<int Function(ffi.Pointer<ffi.Char>)>();\n\n  int atol(ffi.Pointer<ffi.Char> arg0) {\n    return _atol(arg0);\n  }\n\n  late final _atolPtr = _lookup<ffi.NativeFunction<ffi.Long Function(ffi.Pointer<ffi.Char>)>>('atol');\n  late final _atol = _atolPtr.asFunction<int Function(ffi.Pointer<ffi.Char>)>();\n\n  int atoll(ffi.Pointer<ffi.Char> arg0) {\n    return _atoll(arg0);\n  }\n\n  late final _atollPtr = _lookup<ffi.NativeFunction<ffi.LongLong Function(ffi.Pointer<ffi.Char>)>>('atoll');\n  late final _atoll = _atollPtr.asFunction<int Function(ffi.Pointer<ffi.Char>)>();\n\n  ffi.Pointer<ffi.Void> bsearch(\n    ffi.Pointer<ffi.Void> __key,\n    ffi.Pointer<ffi.Void> __base,\n    int __nel,\n    int __width,\n    ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>> __compar,\n  ) {\n    return _bsearch(__key, __base, __nel, __width, __compar);\n  }\n\n  late final _bsearchPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Pointer<ffi.Void> Function(\n            ffi.Pointer<ffi.Void>,\n            ffi.Pointer<ffi.Void>,\n            ffi.Size,\n            ffi.Size,\n            ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,\n          )\n        >\n      >('bsearch');\n  late final _bsearch = _bsearchPtr\n      .asFunction<\n        ffi.Pointer<ffi.Void> Function(\n          ffi.Pointer<ffi.Void>,\n          ffi.Pointer<ffi.Void>,\n          int,\n          int,\n          ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,\n        )\n      >();\n\n  div_t div(int arg0, int arg1) {\n    return _div(arg0, arg1);\n  }\n\n  late final _divPtr = _lookup<ffi.NativeFunction<div_t Function(ffi.Int, ffi.Int)>>('div');\n  late final _div = _divPtr.asFunction<div_t Function(int, int)>();\n\n  void exit(int arg0) {\n    return _exit(arg0);\n  }\n\n  late final _exitPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>('exit');\n  late final _exit = _exitPtr.asFunction<void Function(int)>();\n\n  ffi.Pointer<ffi.Char> getenv(ffi.Pointer<ffi.Char> arg0) {\n    return _getenv(arg0);\n  }\n\n  late final _getenvPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>)>>('getenv');\n  late final _getenv = _getenvPtr.asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>)>();\n\n  int labs(int arg0) {\n    return _labs(arg0);\n  }\n\n  late final _labsPtr = _lookup<ffi.NativeFunction<ffi.Long Function(ffi.Long)>>('labs');\n  late final _labs = _labsPtr.asFunction<int Function(int)>();\n\n  ldiv_t ldiv(int arg0, int arg1) {\n    return _ldiv(arg0, arg1);\n  }\n\n  late final _ldivPtr = _lookup<ffi.NativeFunction<ldiv_t Function(ffi.Long, ffi.Long)>>('ldiv');\n  late final _ldiv = _ldivPtr.asFunction<ldiv_t Function(int, int)>();\n\n  int llabs(int arg0) {\n    return _llabs(arg0);\n  }\n\n  late final _llabsPtr = _lookup<ffi.NativeFunction<ffi.LongLong Function(ffi.LongLong)>>('llabs');\n  late final _llabs = _llabsPtr.asFunction<int Function(int)>();\n\n  lldiv_t lldiv(int arg0, int arg1) {\n    return _lldiv(arg0, arg1);\n  }\n\n  late final _lldivPtr = _lookup<ffi.NativeFunction<lldiv_t Function(ffi.LongLong, ffi.LongLong)>>('lldiv');\n  late final _lldiv = _lldivPtr.asFunction<lldiv_t Function(int, int)>();\n\n  int mblen(ffi.Pointer<ffi.Char> __s, int __n) {\n    return _mblen(__s, __n);\n  }\n\n  late final _mblenPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>, ffi.Size)>>('mblen');\n  late final _mblen = _mblenPtr.asFunction<int Function(ffi.Pointer<ffi.Char>, int)>();\n\n  int mbstowcs(ffi.Pointer<ffi.WChar> arg0, ffi.Pointer<ffi.Char> arg1, int arg2) {\n    return _mbstowcs(arg0, arg1, arg2);\n  }\n\n  late final _mbstowcsPtr =\n      _lookup<ffi.NativeFunction<ffi.Size Function(ffi.Pointer<ffi.WChar>, ffi.Pointer<ffi.Char>, ffi.Size)>>(\n        'mbstowcs',\n      );\n  late final _mbstowcs = _mbstowcsPtr.asFunction<int Function(ffi.Pointer<ffi.WChar>, ffi.Pointer<ffi.Char>, int)>();\n\n  int mbtowc(ffi.Pointer<ffi.WChar> arg0, ffi.Pointer<ffi.Char> arg1, int arg2) {\n    return _mbtowc(arg0, arg1, arg2);\n  }\n\n  late final _mbtowcPtr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.WChar>, ffi.Pointer<ffi.Char>, ffi.Size)>>('mbtowc');\n  late final _mbtowc = _mbtowcPtr.asFunction<int Function(ffi.Pointer<ffi.WChar>, ffi.Pointer<ffi.Char>, int)>();\n\n  void qsort(\n    ffi.Pointer<ffi.Void> __base,\n    int __nel,\n    int __width,\n    ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>> __compar,\n  ) {\n    return _qsort(__base, __nel, __width, __compar);\n  }\n\n  late final _qsortPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Void Function(\n            ffi.Pointer<ffi.Void>,\n            ffi.Size,\n            ffi.Size,\n            ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,\n          )\n        >\n      >('qsort');\n  late final _qsort = _qsortPtr\n      .asFunction<\n        void Function(\n          ffi.Pointer<ffi.Void>,\n          int,\n          int,\n          ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,\n        )\n      >();\n\n  int rand() {\n    return _rand();\n  }\n\n  late final _randPtr = _lookup<ffi.NativeFunction<ffi.Int Function()>>('rand');\n  late final _rand = _randPtr.asFunction<int Function()>();\n\n  void srand(int arg0) {\n    return _srand(arg0);\n  }\n\n  late final _srandPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.UnsignedInt)>>('srand');\n  late final _srand = _srandPtr.asFunction<void Function(int)>();\n\n  double strtod(ffi.Pointer<ffi.Char> arg0, ffi.Pointer<ffi.Pointer<ffi.Char>> arg1) {\n    return _strtod(arg0, arg1);\n  }\n\n  late final _strtodPtr =\n      _lookup<ffi.NativeFunction<ffi.Double Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>)>>(\n        'strtod',\n      );\n  late final _strtod = _strtodPtr\n      .asFunction<double Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>)>();\n\n  double strtof(ffi.Pointer<ffi.Char> arg0, ffi.Pointer<ffi.Pointer<ffi.Char>> arg1) {\n    return _strtof(arg0, arg1);\n  }\n\n  late final _strtofPtr =\n      _lookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>)>>(\n        'strtof',\n      );\n  late final _strtof = _strtofPtr\n      .asFunction<double Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>)>();\n\n  int strtol(ffi.Pointer<ffi.Char> __str, ffi.Pointer<ffi.Pointer<ffi.Char>> __endptr, int __base) {\n    return _strtol(__str, __endptr, __base);\n  }\n\n  late final _strtolPtr =\n      _lookup<\n        ffi.NativeFunction<ffi.Long Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Int)>\n      >('strtol');\n  late final _strtol = _strtolPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, int)>();\n\n  int strtoll(ffi.Pointer<ffi.Char> __str, ffi.Pointer<ffi.Pointer<ffi.Char>> __endptr, int __base) {\n    return _strtoll(__str, __endptr, __base);\n  }\n\n  late final _strtollPtr =\n      _lookup<\n        ffi.NativeFunction<ffi.LongLong Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Int)>\n      >('strtoll');\n  late final _strtoll = _strtollPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, int)>();\n\n  int strtoul(ffi.Pointer<ffi.Char> __str, ffi.Pointer<ffi.Pointer<ffi.Char>> __endptr, int __base) {\n    return _strtoul(__str, __endptr, __base);\n  }\n\n  late final _strtoulPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.UnsignedLong Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Int)\n        >\n      >('strtoul');\n  late final _strtoul = _strtoulPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, int)>();\n\n  int strtoull(ffi.Pointer<ffi.Char> __str, ffi.Pointer<ffi.Pointer<ffi.Char>> __endptr, int __base) {\n    return _strtoull(__str, __endptr, __base);\n  }\n\n  late final _strtoullPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.UnsignedLongLong Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Int)\n        >\n      >('strtoull');\n  late final _strtoull = _strtoullPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, int)>();\n\n  int system(ffi.Pointer<ffi.Char> arg0) {\n    return _system(arg0);\n  }\n\n  late final _systemPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>)>>('system');\n  late final _system = _systemPtr.asFunction<int Function(ffi.Pointer<ffi.Char>)>();\n\n  int wcstombs(ffi.Pointer<ffi.Char> arg0, ffi.Pointer<ffi.WChar> arg1, int arg2) {\n    return _wcstombs(arg0, arg1, arg2);\n  }\n\n  late final _wcstombsPtr =\n      _lookup<ffi.NativeFunction<ffi.Size Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.WChar>, ffi.Size)>>(\n        'wcstombs',\n      );\n  late final _wcstombs = _wcstombsPtr.asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.WChar>, int)>();\n\n  int wctomb(ffi.Pointer<ffi.Char> arg0, int arg1) {\n    return _wctomb(arg0, arg1);\n  }\n\n  late final _wctombPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>, ffi.WChar)>>('wctomb');\n  late final _wctomb = _wctombPtr.asFunction<int Function(ffi.Pointer<ffi.Char>, int)>();\n\n  void _Exit(int arg0) {\n    return __Exit(arg0);\n  }\n\n  late final __ExitPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>('_Exit');\n  late final __Exit = __ExitPtr.asFunction<void Function(int)>();\n\n  int a64l(ffi.Pointer<ffi.Char> arg0) {\n    return _a64l(arg0);\n  }\n\n  late final _a64lPtr = _lookup<ffi.NativeFunction<ffi.Long Function(ffi.Pointer<ffi.Char>)>>('a64l');\n  late final _a64l = _a64lPtr.asFunction<int Function(ffi.Pointer<ffi.Char>)>();\n\n  double drand48() {\n    return _drand48();\n  }\n\n  late final _drand48Ptr = _lookup<ffi.NativeFunction<ffi.Double Function()>>('drand48');\n  late final _drand48 = _drand48Ptr.asFunction<double Function()>();\n\n  ffi.Pointer<ffi.Char> ecvt(double arg0, int arg1, ffi.Pointer<ffi.Int> arg2, ffi.Pointer<ffi.Int> arg3) {\n    return _ecvt(arg0, arg1, arg2, arg3);\n  }\n\n  late final _ecvtPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Pointer<ffi.Char> Function(ffi.Double, ffi.Int, ffi.Pointer<ffi.Int>, ffi.Pointer<ffi.Int>)\n        >\n      >('ecvt');\n  late final _ecvt = _ecvtPtr\n      .asFunction<ffi.Pointer<ffi.Char> Function(double, int, ffi.Pointer<ffi.Int>, ffi.Pointer<ffi.Int>)>();\n\n  double erand48(ffi.Pointer<ffi.UnsignedShort> arg0) {\n    return _erand48(arg0);\n  }\n\n  late final _erand48Ptr = _lookup<ffi.NativeFunction<ffi.Double Function(ffi.Pointer<ffi.UnsignedShort>)>>('erand48');\n  late final _erand48 = _erand48Ptr.asFunction<double Function(ffi.Pointer<ffi.UnsignedShort>)>();\n\n  ffi.Pointer<ffi.Char> fcvt(double arg0, int arg1, ffi.Pointer<ffi.Int> arg2, ffi.Pointer<ffi.Int> arg3) {\n    return _fcvt(arg0, arg1, arg2, arg3);\n  }\n\n  late final _fcvtPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Pointer<ffi.Char> Function(ffi.Double, ffi.Int, ffi.Pointer<ffi.Int>, ffi.Pointer<ffi.Int>)\n        >\n      >('fcvt');\n  late final _fcvt = _fcvtPtr\n      .asFunction<ffi.Pointer<ffi.Char> Function(double, int, ffi.Pointer<ffi.Int>, ffi.Pointer<ffi.Int>)>();\n\n  ffi.Pointer<ffi.Char> gcvt(double arg0, int arg1, ffi.Pointer<ffi.Char> arg2) {\n    return _gcvt(arg0, arg1, arg2);\n  }\n\n  late final _gcvtPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Double, ffi.Int, ffi.Pointer<ffi.Char>)>>('gcvt');\n  late final _gcvt = _gcvtPtr.asFunction<ffi.Pointer<ffi.Char> Function(double, int, ffi.Pointer<ffi.Char>)>();\n\n  int getsubopt(\n    ffi.Pointer<ffi.Pointer<ffi.Char>> arg0,\n    ffi.Pointer<ffi.Pointer<ffi.Char>> arg1,\n    ffi.Pointer<ffi.Pointer<ffi.Char>> arg2,\n  ) {\n    return _getsubopt(arg0, arg1, arg2);\n  }\n\n  late final _getsuboptPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Int Function(\n            ffi.Pointer<ffi.Pointer<ffi.Char>>,\n            ffi.Pointer<ffi.Pointer<ffi.Char>>,\n            ffi.Pointer<ffi.Pointer<ffi.Char>>,\n          )\n        >\n      >('getsubopt');\n  late final _getsubopt = _getsuboptPtr\n      .asFunction<\n        int Function(\n          ffi.Pointer<ffi.Pointer<ffi.Char>>,\n          ffi.Pointer<ffi.Pointer<ffi.Char>>,\n          ffi.Pointer<ffi.Pointer<ffi.Char>>,\n        )\n      >();\n\n  int grantpt(int arg0) {\n    return _grantpt(arg0);\n  }\n\n  late final _grantptPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('grantpt');\n  late final _grantpt = _grantptPtr.asFunction<int Function(int)>();\n\n  ffi.Pointer<ffi.Char> initstate(int arg0, ffi.Pointer<ffi.Char> arg1, int arg2) {\n    return _initstate(arg0, arg1, arg2);\n  }\n\n  late final _initstatePtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.UnsignedInt, ffi.Pointer<ffi.Char>, ffi.Size)>>(\n        'initstate',\n      );\n  late final _initstate = _initstatePtr.asFunction<ffi.Pointer<ffi.Char> Function(int, ffi.Pointer<ffi.Char>, int)>();\n\n  int jrand48(ffi.Pointer<ffi.UnsignedShort> arg0) {\n    return _jrand48(arg0);\n  }\n\n  late final _jrand48Ptr = _lookup<ffi.NativeFunction<ffi.Long Function(ffi.Pointer<ffi.UnsignedShort>)>>('jrand48');\n  late final _jrand48 = _jrand48Ptr.asFunction<int Function(ffi.Pointer<ffi.UnsignedShort>)>();\n\n  ffi.Pointer<ffi.Char> l64a(int arg0) {\n    return _l64a(arg0);\n  }\n\n  late final _l64aPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Long)>>('l64a');\n  late final _l64a = _l64aPtr.asFunction<ffi.Pointer<ffi.Char> Function(int)>();\n\n  void lcong48(ffi.Pointer<ffi.UnsignedShort> arg0) {\n    return _lcong48(arg0);\n  }\n\n  late final _lcong48Ptr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.UnsignedShort>)>>('lcong48');\n  late final _lcong48 = _lcong48Ptr.asFunction<void Function(ffi.Pointer<ffi.UnsignedShort>)>();\n\n  int lrand48() {\n    return _lrand48();\n  }\n\n  late final _lrand48Ptr = _lookup<ffi.NativeFunction<ffi.Long Function()>>('lrand48');\n  late final _lrand48 = _lrand48Ptr.asFunction<int Function()>();\n\n  ffi.Pointer<ffi.Char> mktemp(ffi.Pointer<ffi.Char> arg0) {\n    return _mktemp(arg0);\n  }\n\n  late final _mktempPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>)>>('mktemp');\n  late final _mktemp = _mktempPtr.asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>)>();\n\n  int mkstemp(ffi.Pointer<ffi.Char> arg0) {\n    return _mkstemp(arg0);\n  }\n\n  late final _mkstempPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>)>>('mkstemp');\n  late final _mkstemp = _mkstempPtr.asFunction<int Function(ffi.Pointer<ffi.Char>)>();\n\n  int mrand48() {\n    return _mrand48();\n  }\n\n  late final _mrand48Ptr = _lookup<ffi.NativeFunction<ffi.Long Function()>>('mrand48');\n  late final _mrand48 = _mrand48Ptr.asFunction<int Function()>();\n\n  int nrand48(ffi.Pointer<ffi.UnsignedShort> arg0) {\n    return _nrand48(arg0);\n  }\n\n  late final _nrand48Ptr = _lookup<ffi.NativeFunction<ffi.Long Function(ffi.Pointer<ffi.UnsignedShort>)>>('nrand48');\n  late final _nrand48 = _nrand48Ptr.asFunction<int Function(ffi.Pointer<ffi.UnsignedShort>)>();\n\n  int posix_openpt(int arg0) {\n    return _posix_openpt(arg0);\n  }\n\n  late final _posix_openptPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('posix_openpt');\n  late final _posix_openpt = _posix_openptPtr.asFunction<int Function(int)>();\n\n  ffi.Pointer<ffi.Char> ptsname(int arg0) {\n    return _ptsname(arg0);\n  }\n\n  late final _ptsnamePtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Int)>>('ptsname');\n  late final _ptsname = _ptsnamePtr.asFunction<ffi.Pointer<ffi.Char> Function(int)>();\n\n  int ptsname_r(int fildes, ffi.Pointer<ffi.Char> buffer, int buflen) {\n    return _ptsname_r(fildes, buffer, buflen);\n  }\n\n  late final _ptsname_rPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Pointer<ffi.Char>, ffi.Size)>>(\n    'ptsname_r',\n  );\n  late final _ptsname_r = _ptsname_rPtr.asFunction<int Function(int, ffi.Pointer<ffi.Char>, int)>();\n\n  int putenv(ffi.Pointer<ffi.Char> arg0) {\n    return _putenv(arg0);\n  }\n\n  late final _putenvPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>)>>('putenv');\n  late final _putenv = _putenvPtr.asFunction<int Function(ffi.Pointer<ffi.Char>)>();\n\n  int random() {\n    return _random();\n  }\n\n  late final _randomPtr = _lookup<ffi.NativeFunction<ffi.Long Function()>>('random');\n  late final _random = _randomPtr.asFunction<int Function()>();\n\n  int rand_r(ffi.Pointer<ffi.UnsignedInt> arg0) {\n    return _rand_r(arg0);\n  }\n\n  late final _rand_rPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.UnsignedInt>)>>('rand_r');\n  late final _rand_r = _rand_rPtr.asFunction<int Function(ffi.Pointer<ffi.UnsignedInt>)>();\n\n  ffi.Pointer<ffi.Char> realpath(ffi.Pointer<ffi.Char> arg0, ffi.Pointer<ffi.Char> arg1) {\n    return _realpath(arg0, arg1);\n  }\n\n  late final _realpathPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>(\n        'realpath',\n      );\n  late final _realpath = _realpathPtr\n      .asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>();\n\n  ffi.Pointer<ffi.UnsignedShort> seed48(ffi.Pointer<ffi.UnsignedShort> arg0) {\n    return _seed48(arg0);\n  }\n\n  late final _seed48Ptr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.UnsignedShort> Function(ffi.Pointer<ffi.UnsignedShort>)>>('seed48');\n  late final _seed48 = _seed48Ptr.asFunction<ffi.Pointer<ffi.UnsignedShort> Function(ffi.Pointer<ffi.UnsignedShort>)>();\n\n  int setenv(ffi.Pointer<ffi.Char> __name, ffi.Pointer<ffi.Char> __value, int __overwrite) {\n    return _setenv(__name, __value, __overwrite);\n  }\n\n  late final _setenvPtr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, ffi.Int)>>('setenv');\n  late final _setenv = _setenvPtr.asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, int)>();\n\n  void setkey(ffi.Pointer<ffi.Char> arg0) {\n    return _setkey(arg0);\n  }\n\n  late final _setkeyPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>('setkey');\n  late final _setkey = _setkeyPtr.asFunction<void Function(ffi.Pointer<ffi.Char>)>();\n\n  ffi.Pointer<ffi.Char> setstate(ffi.Pointer<ffi.Char> arg0) {\n    return _setstate(arg0);\n  }\n\n  late final _setstatePtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>)>>(\n    'setstate',\n  );\n  late final _setstate = _setstatePtr.asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>)>();\n\n  void srand48(int arg0) {\n    return _srand48(arg0);\n  }\n\n  late final _srand48Ptr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Long)>>('srand48');\n  late final _srand48 = _srand48Ptr.asFunction<void Function(int)>();\n\n  void srandom(int arg0) {\n    return _srandom(arg0);\n  }\n\n  late final _srandomPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.UnsignedInt)>>('srandom');\n  late final _srandom = _srandomPtr.asFunction<void Function(int)>();\n\n  int unlockpt(int arg0) {\n    return _unlockpt(arg0);\n  }\n\n  late final _unlockptPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('unlockpt');\n  late final _unlockpt = _unlockptPtr.asFunction<int Function(int)>();\n\n  int unsetenv(ffi.Pointer<ffi.Char> arg0) {\n    return _unsetenv(arg0);\n  }\n\n  late final _unsetenvPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>)>>('unsetenv');\n  late final _unsetenv = _unsetenvPtr.asFunction<int Function(ffi.Pointer<ffi.Char>)>();\n\n  int arc4random() {\n    return _arc4random();\n  }\n\n  late final _arc4randomPtr = _lookup<ffi.NativeFunction<ffi.Uint32 Function()>>('arc4random');\n  late final _arc4random = _arc4randomPtr.asFunction<int Function()>();\n\n  void arc4random_addrandom(ffi.Pointer<ffi.UnsignedChar> arg0, int arg1) {\n    return _arc4random_addrandom(arg0, arg1);\n  }\n\n  late final _arc4random_addrandomPtr =\n      _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.UnsignedChar>, ffi.Int)>>('arc4random_addrandom');\n  late final _arc4random_addrandom = _arc4random_addrandomPtr\n      .asFunction<void Function(ffi.Pointer<ffi.UnsignedChar>, int)>();\n\n  void arc4random_buf(ffi.Pointer<ffi.Void> __buf, int __nbytes) {\n    return _arc4random_buf(__buf, __nbytes);\n  }\n\n  late final _arc4random_bufPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Size)>>(\n    'arc4random_buf',\n  );\n  late final _arc4random_buf = _arc4random_bufPtr.asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();\n\n  void arc4random_stir() {\n    return _arc4random_stir();\n  }\n\n  late final _arc4random_stirPtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('arc4random_stir');\n  late final _arc4random_stir = _arc4random_stirPtr.asFunction<void Function()>();\n\n  int arc4random_uniform(int __upper_bound) {\n    return _arc4random_uniform(__upper_bound);\n  }\n\n  late final _arc4random_uniformPtr = _lookup<ffi.NativeFunction<ffi.Uint32 Function(ffi.Uint32)>>(\n    'arc4random_uniform',\n  );\n  late final _arc4random_uniform = _arc4random_uniformPtr.asFunction<int Function(int)>();\n\n  ffi.Pointer<ffi.Char> cgetcap(ffi.Pointer<ffi.Char> arg0, ffi.Pointer<ffi.Char> arg1, int arg2) {\n    return _cgetcap(arg0, arg1, arg2);\n  }\n\n  late final _cgetcapPtr =\n      _lookup<\n        ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, ffi.Int)>\n      >('cgetcap');\n  late final _cgetcap = _cgetcapPtr\n      .asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, int)>();\n\n  int cgetclose() {\n    return _cgetclose();\n  }\n\n  late final _cgetclosePtr = _lookup<ffi.NativeFunction<ffi.Int Function()>>('cgetclose');\n  late final _cgetclose = _cgetclosePtr.asFunction<int Function()>();\n\n  int cgetent(\n    ffi.Pointer<ffi.Pointer<ffi.Char>> arg0,\n    ffi.Pointer<ffi.Pointer<ffi.Char>> arg1,\n    ffi.Pointer<ffi.Char> arg2,\n  ) {\n    return _cgetent(arg0, arg1, arg2);\n  }\n\n  late final _cgetentPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Int Function(\n            ffi.Pointer<ffi.Pointer<ffi.Char>>,\n            ffi.Pointer<ffi.Pointer<ffi.Char>>,\n            ffi.Pointer<ffi.Char>,\n          )\n        >\n      >('cgetent');\n  late final _cgetent = _cgetentPtr\n      .asFunction<\n        int Function(ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Pointer<ffi.Char>)\n      >();\n\n  int cgetfirst(ffi.Pointer<ffi.Pointer<ffi.Char>> arg0, ffi.Pointer<ffi.Pointer<ffi.Char>> arg1) {\n    return _cgetfirst(arg0, arg1);\n  }\n\n  late final _cgetfirstPtr =\n      _lookup<\n        ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Pointer<ffi.Pointer<ffi.Char>>)>\n      >('cgetfirst');\n  late final _cgetfirst = _cgetfirstPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Pointer<ffi.Pointer<ffi.Char>>)>();\n\n  int cgetmatch(ffi.Pointer<ffi.Char> arg0, ffi.Pointer<ffi.Char> arg1) {\n    return _cgetmatch(arg0, arg1);\n  }\n\n  late final _cgetmatchPtr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>('cgetmatch');\n  late final _cgetmatch = _cgetmatchPtr.asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>();\n\n  int cgetnext(ffi.Pointer<ffi.Pointer<ffi.Char>> arg0, ffi.Pointer<ffi.Pointer<ffi.Char>> arg1) {\n    return _cgetnext(arg0, arg1);\n  }\n\n  late final _cgetnextPtr =\n      _lookup<\n        ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Pointer<ffi.Pointer<ffi.Char>>)>\n      >('cgetnext');\n  late final _cgetnext = _cgetnextPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Pointer<ffi.Pointer<ffi.Char>>)>();\n\n  int cgetnum(ffi.Pointer<ffi.Char> arg0, ffi.Pointer<ffi.Char> arg1, ffi.Pointer<ffi.Long> arg2) {\n    return _cgetnum(arg0, arg1, arg2);\n  }\n\n  late final _cgetnumPtr =\n      _lookup<\n        ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Long>)>\n      >('cgetnum');\n  late final _cgetnum = _cgetnumPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Long>)>();\n\n  int cgetset(ffi.Pointer<ffi.Char> arg0) {\n    return _cgetset(arg0);\n  }\n\n  late final _cgetsetPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>)>>('cgetset');\n  late final _cgetset = _cgetsetPtr.asFunction<int Function(ffi.Pointer<ffi.Char>)>();\n\n  int cgetstr(ffi.Pointer<ffi.Char> arg0, ffi.Pointer<ffi.Char> arg1, ffi.Pointer<ffi.Pointer<ffi.Char>> arg2) {\n    return _cgetstr(arg0, arg1, arg2);\n  }\n\n  late final _cgetstrPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>)\n        >\n      >('cgetstr');\n  late final _cgetstr = _cgetstrPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>)>();\n\n  int cgetustr(ffi.Pointer<ffi.Char> arg0, ffi.Pointer<ffi.Char> arg1, ffi.Pointer<ffi.Pointer<ffi.Char>> arg2) {\n    return _cgetustr(arg0, arg1, arg2);\n  }\n\n  late final _cgetustrPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>)\n        >\n      >('cgetustr');\n  late final _cgetustr = _cgetustrPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>)>();\n\n  int daemon(int arg0, int arg1) {\n    return _daemon(arg0, arg1);\n  }\n\n  late final _daemonPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Int)>>('daemon');\n  late final _daemon = _daemonPtr.asFunction<int Function(int, int)>();\n\n  ffi.Pointer<ffi.Char> devname(int arg0, int arg1) {\n    return _devname(arg0, arg1);\n  }\n\n  late final _devnamePtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(dev_t, mode_t)>>('devname');\n  late final _devname = _devnamePtr.asFunction<ffi.Pointer<ffi.Char> Function(int, int)>();\n\n  ffi.Pointer<ffi.Char> devname_r(int arg0, int arg1, ffi.Pointer<ffi.Char> buf, int len) {\n    return _devname_r(arg0, arg1, buf, len);\n  }\n\n  late final _devname_rPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(dev_t, mode_t, ffi.Pointer<ffi.Char>, ffi.Int)>>(\n        'devname_r',\n      );\n  late final _devname_r = _devname_rPtr\n      .asFunction<ffi.Pointer<ffi.Char> Function(int, int, ffi.Pointer<ffi.Char>, int)>();\n\n  ffi.Pointer<ffi.Char> getbsize(ffi.Pointer<ffi.Int> arg0, ffi.Pointer<ffi.Long> arg1) {\n    return _getbsize(arg0, arg1);\n  }\n\n  late final _getbsizePtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Int>, ffi.Pointer<ffi.Long>)>>(\n        'getbsize',\n      );\n  late final _getbsize = _getbsizePtr\n      .asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Int>, ffi.Pointer<ffi.Long>)>();\n\n  int getloadavg(ffi.Pointer<ffi.Double> arg0, int arg1) {\n    return _getloadavg(arg0, arg1);\n  }\n\n  late final _getloadavgPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Double>, ffi.Int)>>(\n    'getloadavg',\n  );\n  late final _getloadavg = _getloadavgPtr.asFunction<int Function(ffi.Pointer<ffi.Double>, int)>();\n\n  ffi.Pointer<ffi.Char> getprogname() {\n    return _getprogname();\n  }\n\n  late final _getprognamePtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function()>>('getprogname');\n  late final _getprogname = _getprognamePtr.asFunction<ffi.Pointer<ffi.Char> Function()>();\n\n  void setprogname(ffi.Pointer<ffi.Char> arg0) {\n    return _setprogname(arg0);\n  }\n\n  late final _setprognamePtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>('setprogname');\n  late final _setprogname = _setprognamePtr.asFunction<void Function(ffi.Pointer<ffi.Char>)>();\n\n  int heapsort(\n    ffi.Pointer<ffi.Void> __base,\n    int __nel,\n    int __width,\n    ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>> __compar,\n  ) {\n    return _heapsort(__base, __nel, __width, __compar);\n  }\n\n  late final _heapsortPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Int Function(\n            ffi.Pointer<ffi.Void>,\n            ffi.Size,\n            ffi.Size,\n            ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,\n          )\n        >\n      >('heapsort');\n  late final _heapsort = _heapsortPtr\n      .asFunction<\n        int Function(\n          ffi.Pointer<ffi.Void>,\n          int,\n          int,\n          ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,\n        )\n      >();\n\n  int mergesort(\n    ffi.Pointer<ffi.Void> __base,\n    int __nel,\n    int __width,\n    ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>> __compar,\n  ) {\n    return _mergesort(__base, __nel, __width, __compar);\n  }\n\n  late final _mergesortPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Int Function(\n            ffi.Pointer<ffi.Void>,\n            ffi.Size,\n            ffi.Size,\n            ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,\n          )\n        >\n      >('mergesort');\n  late final _mergesort = _mergesortPtr\n      .asFunction<\n        int Function(\n          ffi.Pointer<ffi.Void>,\n          int,\n          int,\n          ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,\n        )\n      >();\n\n  void psort(\n    ffi.Pointer<ffi.Void> __base,\n    int __nel,\n    int __width,\n    ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>> __compar,\n  ) {\n    return _psort(__base, __nel, __width, __compar);\n  }\n\n  late final _psortPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Void Function(\n            ffi.Pointer<ffi.Void>,\n            ffi.Size,\n            ffi.Size,\n            ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,\n          )\n        >\n      >('psort');\n  late final _psort = _psortPtr\n      .asFunction<\n        void Function(\n          ffi.Pointer<ffi.Void>,\n          int,\n          int,\n          ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,\n        )\n      >();\n\n  void psort_r(\n    ffi.Pointer<ffi.Void> __base,\n    int __nel,\n    int __width,\n    ffi.Pointer<ffi.Void> arg3,\n    ffi.Pointer<\n      ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>\n    >\n    __compar,\n  ) {\n    return _psort_r(__base, __nel, __width, arg3, __compar);\n  }\n\n  late final _psort_rPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Void Function(\n            ffi.Pointer<ffi.Void>,\n            ffi.Size,\n            ffi.Size,\n            ffi.Pointer<ffi.Void>,\n            ffi.Pointer<\n              ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>\n            >,\n          )\n        >\n      >('psort_r');\n  late final _psort_r = _psort_rPtr\n      .asFunction<\n        void Function(\n          ffi.Pointer<ffi.Void>,\n          int,\n          int,\n          ffi.Pointer<ffi.Void>,\n          ffi.Pointer<\n            ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>\n          >,\n        )\n      >();\n\n  void qsort_r(\n    ffi.Pointer<ffi.Void> __base,\n    int __nel,\n    int __width,\n    ffi.Pointer<ffi.Void> arg3,\n    ffi.Pointer<\n      ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>\n    >\n    __compar,\n  ) {\n    return _qsort_r(__base, __nel, __width, arg3, __compar);\n  }\n\n  late final _qsort_rPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Void Function(\n            ffi.Pointer<ffi.Void>,\n            ffi.Size,\n            ffi.Size,\n            ffi.Pointer<ffi.Void>,\n            ffi.Pointer<\n              ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>\n            >,\n          )\n        >\n      >('qsort_r');\n  late final _qsort_r = _qsort_rPtr\n      .asFunction<\n        void Function(\n          ffi.Pointer<ffi.Void>,\n          int,\n          int,\n          ffi.Pointer<ffi.Void>,\n          ffi.Pointer<\n            ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>\n          >,\n        )\n      >();\n\n  int radixsort(\n    ffi.Pointer<ffi.Pointer<ffi.UnsignedChar>> __base,\n    int __nel,\n    ffi.Pointer<ffi.UnsignedChar> __table,\n    int __endbyte,\n  ) {\n    return _radixsort(__base, __nel, __table, __endbyte);\n  }\n\n  late final _radixsortPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Int Function(\n            ffi.Pointer<ffi.Pointer<ffi.UnsignedChar>>,\n            ffi.Int,\n            ffi.Pointer<ffi.UnsignedChar>,\n            ffi.UnsignedInt,\n          )\n        >\n      >('radixsort');\n  late final _radixsort = _radixsortPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Pointer<ffi.UnsignedChar>>, int, ffi.Pointer<ffi.UnsignedChar>, int)>();\n\n  int rpmatch(ffi.Pointer<ffi.Char> arg0) {\n    return _rpmatch(arg0);\n  }\n\n  late final _rpmatchPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<ffi.Char>)>>('rpmatch');\n  late final _rpmatch = _rpmatchPtr.asFunction<int Function(ffi.Pointer<ffi.Char>)>();\n\n  int sradixsort(\n    ffi.Pointer<ffi.Pointer<ffi.UnsignedChar>> __base,\n    int __nel,\n    ffi.Pointer<ffi.UnsignedChar> __table,\n    int __endbyte,\n  ) {\n    return _sradixsort(__base, __nel, __table, __endbyte);\n  }\n\n  late final _sradixsortPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Int Function(\n            ffi.Pointer<ffi.Pointer<ffi.UnsignedChar>>,\n            ffi.Int,\n            ffi.Pointer<ffi.UnsignedChar>,\n            ffi.UnsignedInt,\n          )\n        >\n      >('sradixsort');\n  late final _sradixsort = _sradixsortPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Pointer<ffi.UnsignedChar>>, int, ffi.Pointer<ffi.UnsignedChar>, int)>();\n\n  void sranddev() {\n    return _sranddev();\n  }\n\n  late final _sranddevPtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('sranddev');\n  late final _sranddev = _sranddevPtr.asFunction<void Function()>();\n\n  void srandomdev() {\n    return _srandomdev();\n  }\n\n  late final _srandomdevPtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('srandomdev');\n  late final _srandomdev = _srandomdevPtr.asFunction<void Function()>();\n\n  int strtonum(\n    ffi.Pointer<ffi.Char> __numstr,\n    int __minval,\n    int __maxval,\n    ffi.Pointer<ffi.Pointer<ffi.Char>> __errstrp,\n  ) {\n    return _strtonum(__numstr, __minval, __maxval, __errstrp);\n  }\n\n  late final _strtonumPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.LongLong Function(ffi.Pointer<ffi.Char>, ffi.LongLong, ffi.LongLong, ffi.Pointer<ffi.Pointer<ffi.Char>>)\n        >\n      >('strtonum');\n  late final _strtonum = _strtonumPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Char>, int, int, ffi.Pointer<ffi.Pointer<ffi.Char>>)>();\n\n  int strtoq(ffi.Pointer<ffi.Char> __str, ffi.Pointer<ffi.Pointer<ffi.Char>> __endptr, int __base) {\n    return _strtoq(__str, __endptr, __base);\n  }\n\n  late final _strtoqPtr =\n      _lookup<\n        ffi.NativeFunction<ffi.LongLong Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Int)>\n      >('strtoq');\n  late final _strtoq = _strtoqPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, int)>();\n\n  int strtouq(ffi.Pointer<ffi.Char> __str, ffi.Pointer<ffi.Pointer<ffi.Char>> __endptr, int __base) {\n    return _strtouq(__str, __endptr, __base);\n  }\n\n  late final _strtouqPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.UnsignedLongLong Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Int)\n        >\n      >('strtouq');\n  late final _strtouq = _strtouqPtr\n      .asFunction<int Function(ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Pointer<ffi.Char>>, int)>();\n\n  late final ffi.Pointer<ffi.Pointer<ffi.Char>> _suboptarg = _lookup<ffi.Pointer<ffi.Char>>('suboptarg');\n\n  ffi.Pointer<ffi.Char> get suboptarg => _suboptarg.value;\n\n  set suboptarg(ffi.Pointer<ffi.Char> value) => _suboptarg.value = value;\n\n  late final ffi.Pointer<ffi.Pointer<ffi.Pointer<ffi.Char>>> _sys_signame = _lookup<ffi.Pointer<ffi.Pointer<ffi.Char>>>(\n    'sys_signame',\n  );\n\n  ffi.Pointer<ffi.Pointer<ffi.Char>> get sys_signame => _sys_signame.value;\n\n  set sys_signame(ffi.Pointer<ffi.Pointer<ffi.Char>> value) => _sys_signame.value = value;\n\n  late final ffi.Pointer<ffi.Pointer<ffi.Pointer<ffi.Char>>> _sys_siglist = _lookup<ffi.Pointer<ffi.Pointer<ffi.Char>>>(\n    'sys_siglist',\n  );\n\n  ffi.Pointer<ffi.Pointer<ffi.Char>> get sys_siglist => _sys_siglist.value;\n\n  set sys_siglist(ffi.Pointer<ffi.Pointer<ffi.Char>> value) => _sys_siglist.value = value;\n\n  int raise(int arg0) {\n    return _raise(arg0);\n  }\n\n  late final _raisePtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('raise');\n  late final _raise = _raisePtr.asFunction<int Function(int)>();\n\n  ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> bsd_signal(\n    int arg0,\n    ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> arg1,\n  ) {\n    return _bsd_signal(arg0, arg1);\n  }\n\n  late final _bsd_signalPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> Function(\n            ffi.Int,\n            ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>,\n          )\n        >\n      >('bsd_signal');\n  late final _bsd_signal = _bsd_signalPtr\n      .asFunction<\n        ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> Function(\n          int,\n          ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>,\n        )\n      >();\n\n  int kill(int arg0, int arg1) {\n    return _kill(arg0, arg1);\n  }\n\n  late final _killPtr = _lookup<ffi.NativeFunction<ffi.Int Function(pid_t, ffi.Int)>>('kill');\n  late final _kill = _killPtr.asFunction<int Function(int, int)>();\n\n  int killpg(int arg0, int arg1) {\n    return _killpg(arg0, arg1);\n  }\n\n  late final _killpgPtr = _lookup<ffi.NativeFunction<ffi.Int Function(pid_t, ffi.Int)>>('killpg');\n  late final _killpg = _killpgPtr.asFunction<int Function(int, int)>();\n\n  int pthread_kill(pthread_t arg0, int arg1) {\n    return _pthread_kill(arg0, arg1);\n  }\n\n  late final _pthread_killPtr = _lookup<ffi.NativeFunction<ffi.Int Function(pthread_t, ffi.Int)>>('pthread_kill');\n  late final _pthread_kill = _pthread_killPtr.asFunction<int Function(pthread_t, int)>();\n\n  int pthread_sigmask(int arg0, ffi.Pointer<sigset_t> arg1, ffi.Pointer<sigset_t> arg2) {\n    return _pthread_sigmask(arg0, arg1, arg2);\n  }\n\n  late final _pthread_sigmaskPtr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Pointer<sigset_t>, ffi.Pointer<sigset_t>)>>(\n        'pthread_sigmask',\n      );\n  late final _pthread_sigmask = _pthread_sigmaskPtr\n      .asFunction<int Function(int, ffi.Pointer<sigset_t>, ffi.Pointer<sigset_t>)>();\n\n  int sigaction1(int arg0, ffi.Pointer<sigaction> arg1, ffi.Pointer<sigaction> arg2) {\n    return _sigaction1(arg0, arg1, arg2);\n  }\n\n  late final _sigaction1Ptr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Pointer<sigaction>, ffi.Pointer<sigaction>)>>(\n        'sigaction',\n      );\n  late final _sigaction1 = _sigaction1Ptr\n      .asFunction<int Function(int, ffi.Pointer<sigaction>, ffi.Pointer<sigaction>)>();\n\n  int sigaddset(ffi.Pointer<sigset_t> arg0, int arg1) {\n    return _sigaddset(arg0, arg1);\n  }\n\n  late final _sigaddsetPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<sigset_t>, ffi.Int)>>('sigaddset');\n  late final _sigaddset = _sigaddsetPtr.asFunction<int Function(ffi.Pointer<sigset_t>, int)>();\n\n  int sigaltstack(ffi.Pointer<stack_t> arg0, ffi.Pointer<stack_t> arg1) {\n    return _sigaltstack(arg0, arg1);\n  }\n\n  late final _sigaltstackPtr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<stack_t>, ffi.Pointer<stack_t>)>>('sigaltstack');\n  late final _sigaltstack = _sigaltstackPtr.asFunction<int Function(ffi.Pointer<stack_t>, ffi.Pointer<stack_t>)>();\n\n  int sigdelset(ffi.Pointer<sigset_t> arg0, int arg1) {\n    return _sigdelset(arg0, arg1);\n  }\n\n  late final _sigdelsetPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<sigset_t>, ffi.Int)>>('sigdelset');\n  late final _sigdelset = _sigdelsetPtr.asFunction<int Function(ffi.Pointer<sigset_t>, int)>();\n\n  int sigemptyset(ffi.Pointer<sigset_t> arg0) {\n    return _sigemptyset(arg0);\n  }\n\n  late final _sigemptysetPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<sigset_t>)>>('sigemptyset');\n  late final _sigemptyset = _sigemptysetPtr.asFunction<int Function(ffi.Pointer<sigset_t>)>();\n\n  int sigfillset(ffi.Pointer<sigset_t> arg0) {\n    return _sigfillset(arg0);\n  }\n\n  late final _sigfillsetPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<sigset_t>)>>('sigfillset');\n  late final _sigfillset = _sigfillsetPtr.asFunction<int Function(ffi.Pointer<sigset_t>)>();\n\n  int sighold(int arg0) {\n    return _sighold(arg0);\n  }\n\n  late final _sigholdPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('sighold');\n  late final _sighold = _sigholdPtr.asFunction<int Function(int)>();\n\n  int sigignore(int arg0) {\n    return _sigignore(arg0);\n  }\n\n  late final _sigignorePtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('sigignore');\n  late final _sigignore = _sigignorePtr.asFunction<int Function(int)>();\n\n  int siginterrupt(int arg0, int arg1) {\n    return _siginterrupt(arg0, arg1);\n  }\n\n  late final _siginterruptPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Int)>>('siginterrupt');\n  late final _siginterrupt = _siginterruptPtr.asFunction<int Function(int, int)>();\n\n  int sigismember(ffi.Pointer<sigset_t> arg0, int arg1) {\n    return _sigismember(arg0, arg1);\n  }\n\n  late final _sigismemberPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<sigset_t>, ffi.Int)>>(\n    'sigismember',\n  );\n  late final _sigismember = _sigismemberPtr.asFunction<int Function(ffi.Pointer<sigset_t>, int)>();\n\n  int sigpause(int arg0) {\n    return _sigpause(arg0);\n  }\n\n  late final _sigpausePtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('sigpause');\n  late final _sigpause = _sigpausePtr.asFunction<int Function(int)>();\n\n  int sigpending(ffi.Pointer<sigset_t> arg0) {\n    return _sigpending(arg0);\n  }\n\n  late final _sigpendingPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<sigset_t>)>>('sigpending');\n  late final _sigpending = _sigpendingPtr.asFunction<int Function(ffi.Pointer<sigset_t>)>();\n\n  int sigprocmask(int arg0, ffi.Pointer<sigset_t> arg1, ffi.Pointer<sigset_t> arg2) {\n    return _sigprocmask(arg0, arg1, arg2);\n  }\n\n  late final _sigprocmaskPtr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Pointer<sigset_t>, ffi.Pointer<sigset_t>)>>(\n        'sigprocmask',\n      );\n  late final _sigprocmask = _sigprocmaskPtr\n      .asFunction<int Function(int, ffi.Pointer<sigset_t>, ffi.Pointer<sigset_t>)>();\n\n  int sigrelse(int arg0) {\n    return _sigrelse(arg0);\n  }\n\n  late final _sigrelsePtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('sigrelse');\n  late final _sigrelse = _sigrelsePtr.asFunction<int Function(int)>();\n\n  ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> sigset(\n    int arg0,\n    ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> arg1,\n  ) {\n    return _sigset(arg0, arg1);\n  }\n\n  late final _sigsetPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> Function(\n            ffi.Int,\n            ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>,\n          )\n        >\n      >('sigset');\n  late final _sigset = _sigsetPtr\n      .asFunction<\n        ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> Function(\n          int,\n          ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>,\n        )\n      >();\n\n  int sigsuspend(ffi.Pointer<sigset_t> arg0) {\n    return _sigsuspend(arg0);\n  }\n\n  late final _sigsuspendPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<sigset_t>)>>('sigsuspend');\n  late final _sigsuspend = _sigsuspendPtr.asFunction<int Function(ffi.Pointer<sigset_t>)>();\n\n  int sigwait(ffi.Pointer<sigset_t> arg0, ffi.Pointer<ffi.Int> arg1) {\n    return _sigwait(arg0, arg1);\n  }\n\n  late final _sigwaitPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Pointer<sigset_t>, ffi.Pointer<ffi.Int>)>>(\n    'sigwait',\n  );\n  late final _sigwait = _sigwaitPtr.asFunction<int Function(ffi.Pointer<sigset_t>, ffi.Pointer<ffi.Int>)>();\n\n  void psignal(int arg0, ffi.Pointer<ffi.Char> arg1) {\n    return _psignal(arg0, arg1);\n  }\n\n  late final _psignalPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int, ffi.Pointer<ffi.Char>)>>('psignal');\n  late final _psignal = _psignalPtr.asFunction<void Function(int, ffi.Pointer<ffi.Char>)>();\n\n  int sigblock(int arg0) {\n    return _sigblock(arg0);\n  }\n\n  late final _sigblockPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('sigblock');\n  late final _sigblock = _sigblockPtr.asFunction<int Function(int)>();\n\n  int sigsetmask(int arg0) {\n    return _sigsetmask(arg0);\n  }\n\n  late final _sigsetmaskPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int)>>('sigsetmask');\n  late final _sigsetmask = _sigsetmaskPtr.asFunction<int Function(int)>();\n\n  int sigvec1(int arg0, ffi.Pointer<sigvec> arg1, ffi.Pointer<sigvec> arg2) {\n    return _sigvec1(arg0, arg1, arg2);\n  }\n\n  late final _sigvec1Ptr =\n      _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Pointer<sigvec>, ffi.Pointer<sigvec>)>>('sigvec');\n  late final _sigvec1 = _sigvec1Ptr.asFunction<int Function(int, ffi.Pointer<sigvec>, ffi.Pointer<sigvec>)>();\n\n  void init_signals() {\n    return _init_signals();\n  }\n\n  late final _init_signalsPtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('init_signals');\n  late final _init_signals = _init_signalsPtr.asFunction<void Function()>();\n\n  void cleanup_signals() {\n    return _cleanup_signals();\n  }\n\n  late final _cleanup_signalsPtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('cleanup_signals');\n  late final _cleanup_signals = _cleanup_signalsPtr.asFunction<void Function()>();\n\n  ffi.Pointer<ffi.Char> parseCli(int argc, ffi.Pointer<ffi.Pointer<ffi.Char>> argv) {\n    return _parseCli(argc, argv);\n  }\n\n  late final _parseCliPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Int, ffi.Pointer<ffi.Pointer<ffi.Char>>)>>(\n        'parseCli',\n      );\n  late final _parseCli = _parseCliPtr\n      .asFunction<ffi.Pointer<ffi.Char> Function(int, ffi.Pointer<ffi.Pointer<ffi.Char>>)>();\n\n  void cleanup() {\n    return _cleanup();\n  }\n\n  late final _cleanupPtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('cleanup');\n  late final _cleanup = _cleanupPtr.asFunction<void Function()>();\n\n  ffi.Pointer<ffi.Char> setup(\n    ffi.Pointer<ffi.Char> baseDir,\n    ffi.Pointer<ffi.Char> workingDir,\n    ffi.Pointer<ffi.Char> tempDir,\n    int mode,\n    ffi.Pointer<ffi.Char> listen,\n    ffi.Pointer<ffi.Char> secret,\n    int statusPort,\n    int debug,\n  ) {\n    return _setup(baseDir, workingDir, tempDir, mode, listen, secret, statusPort, debug);\n  }\n\n  late final _setupPtr =\n      _lookup<\n        ffi.NativeFunction<\n          ffi.Pointer<ffi.Char> Function(\n            ffi.Pointer<ffi.Char>,\n            ffi.Pointer<ffi.Char>,\n            ffi.Pointer<ffi.Char>,\n            ffi.Int,\n            ffi.Pointer<ffi.Char>,\n            ffi.Pointer<ffi.Char>,\n            ffi.LongLong,\n            GoUint8,\n          )\n        >\n      >('setup');\n  late final _setup = _setupPtr\n      .asFunction<\n        ffi.Pointer<ffi.Char> Function(\n          ffi.Pointer<ffi.Char>,\n          ffi.Pointer<ffi.Char>,\n          ffi.Pointer<ffi.Char>,\n          int,\n          ffi.Pointer<ffi.Char>,\n          ffi.Pointer<ffi.Char>,\n          int,\n          int,\n        )\n      >();\n\n  void freeString(ffi.Pointer<ffi.Char> str) {\n    return _freeString(str);\n  }\n\n  late final _freeStringPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>('freeString');\n  late final _freeString = _freeStringPtr.asFunction<void Function(ffi.Pointer<ffi.Char>)>();\n\n  ffi.Pointer<ffi.Char> start(ffi.Pointer<ffi.Char> configPath, int disableMemoryLimit) {\n    return _start(configPath, disableMemoryLimit);\n  }\n\n  late final _startPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>, GoUint8)>>(\n    'start',\n  );\n  late final _start = _startPtr.asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>, int)>();\n\n  ffi.Pointer<ffi.Char> stop() {\n    return _stop();\n  }\n\n  late final _stopPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function()>>('stop');\n  late final _stop = _stopPtr.asFunction<ffi.Pointer<ffi.Char> Function()>();\n\n  ffi.Pointer<ffi.Char> restart(ffi.Pointer<ffi.Char> configPath, int disableMemoryLimit) {\n    return _restart(configPath, disableMemoryLimit);\n  }\n\n  late final _restartPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>, GoUint8)>>(\n    'restart',\n  );\n  late final _restart = _restartPtr.asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>, int)>();\n\n  ffi.Pointer<ffi.Char> GetServerPublicKey() {\n    return _GetServerPublicKey();\n  }\n\n  late final _GetServerPublicKeyPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function()>>(\n    'GetServerPublicKey',\n  );\n  late final _GetServerPublicKey = _GetServerPublicKeyPtr.asFunction<ffi.Pointer<ffi.Char> Function()>();\n\n  ffi.Pointer<ffi.Char> AddGrpcClientPublicKey(ffi.Pointer<ffi.Char> clientPublicKey) {\n    return _AddGrpcClientPublicKey(clientPublicKey);\n  }\n\n  late final _AddGrpcClientPublicKeyPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>)>>('AddGrpcClientPublicKey');\n  late final _AddGrpcClientPublicKey =\n      _AddGrpcClientPublicKeyPtr.asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>)>();\n\n  void closeGrpc(int mode) {\n    return _closeGrpc(mode);\n  }\n\n  late final _closeGrpcPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>('closeGrpc');\n  late final _closeGrpc = _closeGrpcPtr.asFunction<void Function(int)>();\n\n  ffi.Pointer<ffi.Char> StartCoreGrpcServer(ffi.Pointer<ffi.Char> listenAddress) {\n    return _StartCoreGrpcServer(listenAddress);\n  }\n\n  late final _StartCoreGrpcServerPtr =\n      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>)>>('StartCoreGrpcServer');\n  late final _StartCoreGrpcServer =\n      _StartCoreGrpcServerPtr.asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>)>();\n}\n\nfinal class __mbstate_t extends ffi.Union {\n  @ffi.Array.multi([128])\n  external ffi.Array<ffi.Char> __mbstate8;\n\n  @ffi.LongLong()\n  external int _mbstateL;\n}\n\nfinal class __darwin_pthread_handler_rec extends ffi.Struct {\n  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>> __routine;\n\n  external ffi.Pointer<ffi.Void> __arg;\n\n  external ffi.Pointer<__darwin_pthread_handler_rec> __next;\n}\n\nfinal class _opaque_pthread_attr_t extends ffi.Struct {\n  @ffi.Long()\n  external int __sig;\n\n  @ffi.Array.multi([56])\n  external ffi.Array<ffi.Char> __opaque;\n}\n\nfinal class _opaque_pthread_cond_t extends ffi.Struct {\n  @ffi.Long()\n  external int __sig;\n\n  @ffi.Array.multi([40])\n  external ffi.Array<ffi.Char> __opaque;\n}\n\nfinal class _opaque_pthread_condattr_t extends ffi.Struct {\n  @ffi.Long()\n  external int __sig;\n\n  @ffi.Array.multi([8])\n  external ffi.Array<ffi.Char> __opaque;\n}\n\nfinal class _opaque_pthread_mutex_t extends ffi.Struct {\n  @ffi.Long()\n  external int __sig;\n\n  @ffi.Array.multi([56])\n  external ffi.Array<ffi.Char> __opaque;\n}\n\nfinal class _opaque_pthread_mutexattr_t extends ffi.Struct {\n  @ffi.Long()\n  external int __sig;\n\n  @ffi.Array.multi([8])\n  external ffi.Array<ffi.Char> __opaque;\n}\n\nfinal class _opaque_pthread_once_t extends ffi.Struct {\n  @ffi.Long()\n  external int __sig;\n\n  @ffi.Array.multi([8])\n  external ffi.Array<ffi.Char> __opaque;\n}\n\nfinal class _opaque_pthread_rwlock_t extends ffi.Struct {\n  @ffi.Long()\n  external int __sig;\n\n  @ffi.Array.multi([192])\n  external ffi.Array<ffi.Char> __opaque;\n}\n\nfinal class _opaque_pthread_rwlockattr_t extends ffi.Struct {\n  @ffi.Long()\n  external int __sig;\n\n  @ffi.Array.multi([16])\n  external ffi.Array<ffi.Char> __opaque;\n}\n\nfinal class _opaque_pthread_t extends ffi.Struct {\n  @ffi.Long()\n  external int __sig;\n\n  external ffi.Pointer<__darwin_pthread_handler_rec> __cleanup_stack;\n\n  @ffi.Array.multi([8176])\n  external ffi.Array<ffi.Char> __opaque;\n}\n\nfinal class _GoString_ extends ffi.Struct {\n  external ffi.Pointer<ffi.Char> p;\n\n  @ptrdiff_t()\n  external int n;\n}\n\ntypedef ptrdiff_t = __darwin_ptrdiff_t;\ntypedef __darwin_ptrdiff_t = ffi.Long;\ntypedef Dart__darwin_ptrdiff_t = int;\n\nenum idtype_t {\n  P_ALL(0),\n  P_PID(1),\n  P_PGID(2);\n\n  final int value;\n  const idtype_t(this.value);\n\n  static idtype_t fromValue(int value) => switch (value) {\n    0 => P_ALL,\n    1 => P_PID,\n    2 => P_PGID,\n    _ => throw ArgumentError(\"Unknown value for idtype_t: $value\"),\n  };\n}\n\nfinal class __darwin_arm_exception_state extends ffi.Struct {\n  @__uint32_t()\n  external int __exception;\n\n  @__uint32_t()\n  external int __fsr;\n\n  @__uint32_t()\n  external int __far;\n}\n\ntypedef __uint32_t = ffi.UnsignedInt;\ntypedef Dart__uint32_t = int;\n\nfinal class __darwin_arm_exception_state64 extends ffi.Struct {\n  @__uint64_t()\n  external int __far;\n\n  @__uint32_t()\n  external int __esr;\n\n  @__uint32_t()\n  external int __exception;\n}\n\ntypedef __uint64_t = ffi.UnsignedLongLong;\ntypedef Dart__uint64_t = int;\n\nfinal class __darwin_arm_thread_state extends ffi.Struct {\n  @ffi.Array.multi([13])\n  external ffi.Array<__uint32_t> __r;\n\n  @__uint32_t()\n  external int __sp;\n\n  @__uint32_t()\n  external int __lr;\n\n  @__uint32_t()\n  external int __pc;\n\n  @__uint32_t()\n  external int __cpsr;\n}\n\nfinal class __darwin_arm_thread_state64 extends ffi.Struct {\n  @ffi.Array.multi([29])\n  external ffi.Array<__uint64_t> __x;\n\n  @__uint64_t()\n  external int __fp;\n\n  @__uint64_t()\n  external int __lr;\n\n  @__uint64_t()\n  external int __sp;\n\n  @__uint64_t()\n  external int __pc;\n\n  @__uint32_t()\n  external int __cpsr;\n\n  @__uint32_t()\n  external int __pad;\n}\n\nfinal class __darwin_arm_vfp_state extends ffi.Struct {\n  @ffi.Array.multi([64])\n  external ffi.Array<__uint32_t> __r;\n\n  @__uint32_t()\n  external int __fpscr;\n}\n\nfinal class __darwin_arm_neon_state64 extends ffi.Opaque {}\n\nfinal class __darwin_arm_neon_state extends ffi.Opaque {}\n\nfinal class __arm_pagein_state extends ffi.Struct {\n  @ffi.Int()\n  external int __pagein_error;\n}\n\nfinal class __arm_legacy_debug_state extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint32_t> __bvr;\n\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint32_t> __bcr;\n\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint32_t> __wvr;\n\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint32_t> __wcr;\n}\n\nfinal class __darwin_arm_debug_state32 extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint32_t> __bvr;\n\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint32_t> __bcr;\n\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint32_t> __wvr;\n\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint32_t> __wcr;\n\n  @__uint64_t()\n  external int __mdscr_el1;\n}\n\nfinal class __darwin_arm_debug_state64 extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint64_t> __bvr;\n\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint64_t> __bcr;\n\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint64_t> __wvr;\n\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint64_t> __wcr;\n\n  @__uint64_t()\n  external int __mdscr_el1;\n}\n\nfinal class __darwin_arm_cpmu_state64 extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<__uint64_t> __ctrs;\n}\n\nfinal class __darwin_mcontext32 extends ffi.Struct {\n  external __darwin_arm_exception_state __es;\n\n  external __darwin_arm_thread_state __ss;\n\n  external __darwin_arm_vfp_state __fs;\n}\n\nfinal class __darwin_mcontext64 extends ffi.Opaque {}\n\nfinal class __darwin_sigaltstack extends ffi.Struct {\n  external ffi.Pointer<ffi.Void> ss_sp;\n\n  @__darwin_size_t()\n  external int ss_size;\n\n  @ffi.Int()\n  external int ss_flags;\n}\n\ntypedef __darwin_size_t = ffi.UnsignedLong;\ntypedef Dart__darwin_size_t = int;\n\nfinal class __darwin_ucontext extends ffi.Struct {\n  @ffi.Int()\n  external int uc_onstack;\n\n  @__darwin_sigset_t()\n  external int uc_sigmask;\n\n  external __darwin_sigaltstack uc_stack;\n\n  external ffi.Pointer<__darwin_ucontext> uc_link;\n\n  @__darwin_size_t()\n  external int uc_mcsize;\n\n  external ffi.Pointer<__darwin_mcontext64> uc_mcontext;\n}\n\ntypedef __darwin_sigset_t = __uint32_t;\n\nfinal class sigval extends ffi.Union {\n  @ffi.Int()\n  external int sival_int;\n\n  external ffi.Pointer<ffi.Void> sival_ptr;\n}\n\nfinal class sigevent extends ffi.Struct {\n  @ffi.Int()\n  external int sigev_notify;\n\n  @ffi.Int()\n  external int sigev_signo;\n\n  external sigval sigev_value;\n\n  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function(sigval)>> sigev_notify_function;\n\n  external ffi.Pointer<pthread_attr_t> sigev_notify_attributes;\n}\n\ntypedef pthread_attr_t = __darwin_pthread_attr_t;\ntypedef __darwin_pthread_attr_t = _opaque_pthread_attr_t;\n\nfinal class __siginfo extends ffi.Struct {\n  @ffi.Int()\n  external int si_signo;\n\n  @ffi.Int()\n  external int si_errno;\n\n  @ffi.Int()\n  external int si_code;\n\n  @pid_t()\n  external int si_pid;\n\n  @uid_t()\n  external int si_uid;\n\n  @ffi.Int()\n  external int si_status;\n\n  external ffi.Pointer<ffi.Void> si_addr;\n\n  external sigval si_value;\n\n  @ffi.Long()\n  external int si_band;\n\n  @ffi.Array.multi([7])\n  external ffi.Array<ffi.UnsignedLong> __pad;\n}\n\ntypedef pid_t = __darwin_pid_t;\ntypedef __darwin_pid_t = __int32_t;\ntypedef __int32_t = ffi.Int;\ntypedef Dart__int32_t = int;\ntypedef uid_t = __darwin_uid_t;\ntypedef __darwin_uid_t = __uint32_t;\n\nfinal class __sigaction_u extends ffi.Union {\n  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> __sa_handler;\n\n  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int, ffi.Pointer<__siginfo>, ffi.Pointer<ffi.Void>)>>\n  __sa_sigaction;\n}\n\nfinal class __sigaction extends ffi.Struct {\n  external __sigaction_u __sigaction_u1;\n\n  external ffi.Pointer<\n    ffi.NativeFunction<\n      ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int, ffi.Int, ffi.Pointer<siginfo_t>, ffi.Pointer<ffi.Void>)\n    >\n  >\n  sa_tramp;\n\n  @sigset_t()\n  external int sa_mask;\n\n  @ffi.Int()\n  external int sa_flags;\n}\n\ntypedef siginfo_t = __siginfo;\ntypedef sigset_t = __darwin_sigset_t;\n\nfinal class sigaction extends ffi.Struct {\n  external __sigaction_u __sigaction_u1;\n\n  @sigset_t()\n  external int sa_mask;\n\n  @ffi.Int()\n  external int sa_flags;\n}\n\nfinal class sigvec extends ffi.Struct {\n  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> sv_handler;\n\n  @ffi.Int()\n  external int sv_mask;\n\n  @ffi.Int()\n  external int sv_flags;\n}\n\nfinal class sigstack extends ffi.Struct {\n  external ffi.Pointer<ffi.Char> ss_sp;\n\n  @ffi.Int()\n  external int ss_onstack;\n}\n\nfinal class timeval extends ffi.Struct {\n  @__darwin_time_t()\n  external int tv_sec;\n\n  @__darwin_suseconds_t()\n  external int tv_usec;\n}\n\ntypedef __darwin_time_t = ffi.Long;\ntypedef Dart__darwin_time_t = int;\ntypedef __darwin_suseconds_t = __int32_t;\n\nfinal class rusage extends ffi.Struct {\n  external timeval ru_utime;\n\n  external timeval ru_stime;\n\n  @ffi.Long()\n  external int ru_maxrss;\n\n  @ffi.Long()\n  external int ru_ixrss;\n\n  @ffi.Long()\n  external int ru_idrss;\n\n  @ffi.Long()\n  external int ru_isrss;\n\n  @ffi.Long()\n  external int ru_minflt;\n\n  @ffi.Long()\n  external int ru_majflt;\n\n  @ffi.Long()\n  external int ru_nswap;\n\n  @ffi.Long()\n  external int ru_inblock;\n\n  @ffi.Long()\n  external int ru_oublock;\n\n  @ffi.Long()\n  external int ru_msgsnd;\n\n  @ffi.Long()\n  external int ru_msgrcv;\n\n  @ffi.Long()\n  external int ru_nsignals;\n\n  @ffi.Long()\n  external int ru_nvcsw;\n\n  @ffi.Long()\n  external int ru_nivcsw;\n}\n\nfinal class rusage_info_v0 extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<ffi.Uint8> ri_uuid;\n\n  @ffi.Uint64()\n  external int ri_user_time;\n\n  @ffi.Uint64()\n  external int ri_system_time;\n\n  @ffi.Uint64()\n  external int ri_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_pageins;\n\n  @ffi.Uint64()\n  external int ri_wired_size;\n\n  @ffi.Uint64()\n  external int ri_resident_size;\n\n  @ffi.Uint64()\n  external int ri_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_proc_start_abstime;\n\n  @ffi.Uint64()\n  external int ri_proc_exit_abstime;\n}\n\nfinal class rusage_info_v1 extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<ffi.Uint8> ri_uuid;\n\n  @ffi.Uint64()\n  external int ri_user_time;\n\n  @ffi.Uint64()\n  external int ri_system_time;\n\n  @ffi.Uint64()\n  external int ri_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_pageins;\n\n  @ffi.Uint64()\n  external int ri_wired_size;\n\n  @ffi.Uint64()\n  external int ri_resident_size;\n\n  @ffi.Uint64()\n  external int ri_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_proc_start_abstime;\n\n  @ffi.Uint64()\n  external int ri_proc_exit_abstime;\n\n  @ffi.Uint64()\n  external int ri_child_user_time;\n\n  @ffi.Uint64()\n  external int ri_child_system_time;\n\n  @ffi.Uint64()\n  external int ri_child_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_pageins;\n\n  @ffi.Uint64()\n  external int ri_child_elapsed_abstime;\n}\n\nfinal class rusage_info_v2 extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<ffi.Uint8> ri_uuid;\n\n  @ffi.Uint64()\n  external int ri_user_time;\n\n  @ffi.Uint64()\n  external int ri_system_time;\n\n  @ffi.Uint64()\n  external int ri_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_pageins;\n\n  @ffi.Uint64()\n  external int ri_wired_size;\n\n  @ffi.Uint64()\n  external int ri_resident_size;\n\n  @ffi.Uint64()\n  external int ri_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_proc_start_abstime;\n\n  @ffi.Uint64()\n  external int ri_proc_exit_abstime;\n\n  @ffi.Uint64()\n  external int ri_child_user_time;\n\n  @ffi.Uint64()\n  external int ri_child_system_time;\n\n  @ffi.Uint64()\n  external int ri_child_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_pageins;\n\n  @ffi.Uint64()\n  external int ri_child_elapsed_abstime;\n\n  @ffi.Uint64()\n  external int ri_diskio_bytesread;\n\n  @ffi.Uint64()\n  external int ri_diskio_byteswritten;\n}\n\nfinal class rusage_info_v3 extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<ffi.Uint8> ri_uuid;\n\n  @ffi.Uint64()\n  external int ri_user_time;\n\n  @ffi.Uint64()\n  external int ri_system_time;\n\n  @ffi.Uint64()\n  external int ri_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_pageins;\n\n  @ffi.Uint64()\n  external int ri_wired_size;\n\n  @ffi.Uint64()\n  external int ri_resident_size;\n\n  @ffi.Uint64()\n  external int ri_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_proc_start_abstime;\n\n  @ffi.Uint64()\n  external int ri_proc_exit_abstime;\n\n  @ffi.Uint64()\n  external int ri_child_user_time;\n\n  @ffi.Uint64()\n  external int ri_child_system_time;\n\n  @ffi.Uint64()\n  external int ri_child_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_pageins;\n\n  @ffi.Uint64()\n  external int ri_child_elapsed_abstime;\n\n  @ffi.Uint64()\n  external int ri_diskio_bytesread;\n\n  @ffi.Uint64()\n  external int ri_diskio_byteswritten;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_default;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_maintenance;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_background;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_utility;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_legacy;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_user_initiated;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_user_interactive;\n\n  @ffi.Uint64()\n  external int ri_billed_system_time;\n\n  @ffi.Uint64()\n  external int ri_serviced_system_time;\n}\n\nfinal class rusage_info_v4 extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<ffi.Uint8> ri_uuid;\n\n  @ffi.Uint64()\n  external int ri_user_time;\n\n  @ffi.Uint64()\n  external int ri_system_time;\n\n  @ffi.Uint64()\n  external int ri_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_pageins;\n\n  @ffi.Uint64()\n  external int ri_wired_size;\n\n  @ffi.Uint64()\n  external int ri_resident_size;\n\n  @ffi.Uint64()\n  external int ri_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_proc_start_abstime;\n\n  @ffi.Uint64()\n  external int ri_proc_exit_abstime;\n\n  @ffi.Uint64()\n  external int ri_child_user_time;\n\n  @ffi.Uint64()\n  external int ri_child_system_time;\n\n  @ffi.Uint64()\n  external int ri_child_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_pageins;\n\n  @ffi.Uint64()\n  external int ri_child_elapsed_abstime;\n\n  @ffi.Uint64()\n  external int ri_diskio_bytesread;\n\n  @ffi.Uint64()\n  external int ri_diskio_byteswritten;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_default;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_maintenance;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_background;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_utility;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_legacy;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_user_initiated;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_user_interactive;\n\n  @ffi.Uint64()\n  external int ri_billed_system_time;\n\n  @ffi.Uint64()\n  external int ri_serviced_system_time;\n\n  @ffi.Uint64()\n  external int ri_logical_writes;\n\n  @ffi.Uint64()\n  external int ri_lifetime_max_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_instructions;\n\n  @ffi.Uint64()\n  external int ri_cycles;\n\n  @ffi.Uint64()\n  external int ri_billed_energy;\n\n  @ffi.Uint64()\n  external int ri_serviced_energy;\n\n  @ffi.Uint64()\n  external int ri_interval_max_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_runnable_time;\n}\n\nfinal class rusage_info_v5 extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<ffi.Uint8> ri_uuid;\n\n  @ffi.Uint64()\n  external int ri_user_time;\n\n  @ffi.Uint64()\n  external int ri_system_time;\n\n  @ffi.Uint64()\n  external int ri_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_pageins;\n\n  @ffi.Uint64()\n  external int ri_wired_size;\n\n  @ffi.Uint64()\n  external int ri_resident_size;\n\n  @ffi.Uint64()\n  external int ri_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_proc_start_abstime;\n\n  @ffi.Uint64()\n  external int ri_proc_exit_abstime;\n\n  @ffi.Uint64()\n  external int ri_child_user_time;\n\n  @ffi.Uint64()\n  external int ri_child_system_time;\n\n  @ffi.Uint64()\n  external int ri_child_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_pageins;\n\n  @ffi.Uint64()\n  external int ri_child_elapsed_abstime;\n\n  @ffi.Uint64()\n  external int ri_diskio_bytesread;\n\n  @ffi.Uint64()\n  external int ri_diskio_byteswritten;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_default;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_maintenance;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_background;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_utility;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_legacy;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_user_initiated;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_user_interactive;\n\n  @ffi.Uint64()\n  external int ri_billed_system_time;\n\n  @ffi.Uint64()\n  external int ri_serviced_system_time;\n\n  @ffi.Uint64()\n  external int ri_logical_writes;\n\n  @ffi.Uint64()\n  external int ri_lifetime_max_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_instructions;\n\n  @ffi.Uint64()\n  external int ri_cycles;\n\n  @ffi.Uint64()\n  external int ri_billed_energy;\n\n  @ffi.Uint64()\n  external int ri_serviced_energy;\n\n  @ffi.Uint64()\n  external int ri_interval_max_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_runnable_time;\n\n  @ffi.Uint64()\n  external int ri_flags;\n}\n\nfinal class rusage_info_v6 extends ffi.Struct {\n  @ffi.Array.multi([16])\n  external ffi.Array<ffi.Uint8> ri_uuid;\n\n  @ffi.Uint64()\n  external int ri_user_time;\n\n  @ffi.Uint64()\n  external int ri_system_time;\n\n  @ffi.Uint64()\n  external int ri_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_pageins;\n\n  @ffi.Uint64()\n  external int ri_wired_size;\n\n  @ffi.Uint64()\n  external int ri_resident_size;\n\n  @ffi.Uint64()\n  external int ri_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_proc_start_abstime;\n\n  @ffi.Uint64()\n  external int ri_proc_exit_abstime;\n\n  @ffi.Uint64()\n  external int ri_child_user_time;\n\n  @ffi.Uint64()\n  external int ri_child_system_time;\n\n  @ffi.Uint64()\n  external int ri_child_pkg_idle_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_interrupt_wkups;\n\n  @ffi.Uint64()\n  external int ri_child_pageins;\n\n  @ffi.Uint64()\n  external int ri_child_elapsed_abstime;\n\n  @ffi.Uint64()\n  external int ri_diskio_bytesread;\n\n  @ffi.Uint64()\n  external int ri_diskio_byteswritten;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_default;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_maintenance;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_background;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_utility;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_legacy;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_user_initiated;\n\n  @ffi.Uint64()\n  external int ri_cpu_time_qos_user_interactive;\n\n  @ffi.Uint64()\n  external int ri_billed_system_time;\n\n  @ffi.Uint64()\n  external int ri_serviced_system_time;\n\n  @ffi.Uint64()\n  external int ri_logical_writes;\n\n  @ffi.Uint64()\n  external int ri_lifetime_max_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_instructions;\n\n  @ffi.Uint64()\n  external int ri_cycles;\n\n  @ffi.Uint64()\n  external int ri_billed_energy;\n\n  @ffi.Uint64()\n  external int ri_serviced_energy;\n\n  @ffi.Uint64()\n  external int ri_interval_max_phys_footprint;\n\n  @ffi.Uint64()\n  external int ri_runnable_time;\n\n  @ffi.Uint64()\n  external int ri_flags;\n\n  @ffi.Uint64()\n  external int ri_user_ptime;\n\n  @ffi.Uint64()\n  external int ri_system_ptime;\n\n  @ffi.Uint64()\n  external int ri_pinstructions;\n\n  @ffi.Uint64()\n  external int ri_pcycles;\n\n  @ffi.Uint64()\n  external int ri_energy_nj;\n\n  @ffi.Uint64()\n  external int ri_penergy_nj;\n\n  @ffi.Uint64()\n  external int ri_secure_time_in_system;\n\n  @ffi.Uint64()\n  external int ri_secure_ptime_in_system;\n\n  @ffi.Array.multi([12])\n  external ffi.Array<ffi.Uint64> ri_reserved;\n}\n\nfinal class rlimit extends ffi.Struct {\n  @rlim_t()\n  external int rlim_cur;\n\n  @rlim_t()\n  external int rlim_max;\n}\n\ntypedef rlim_t = __uint64_t;\n\nfinal class proc_rlimit_control_wakeupmon extends ffi.Struct {\n  @ffi.Uint32()\n  external int wm_flags;\n\n  @ffi.Int32()\n  external int wm_rate;\n}\n\ntypedef id_t = __darwin_id_t;\ntypedef __darwin_id_t = __uint32_t;\n\n@ffi.Packed(1)\nfinal class _OSUnalignedU16 extends ffi.Struct {\n  @ffi.Uint16()\n  external int __val;\n}\n\n@ffi.Packed(1)\nfinal class _OSUnalignedU32 extends ffi.Struct {\n  @ffi.Uint32()\n  external int __val;\n}\n\n@ffi.Packed(1)\nfinal class _OSUnalignedU64 extends ffi.Struct {\n  @ffi.Uint64()\n  external int __val;\n}\n\nfinal class wait extends ffi.Opaque {}\n\nfinal class div_t extends ffi.Struct {\n  @ffi.Int()\n  external int quot;\n\n  @ffi.Int()\n  external int rem;\n}\n\nfinal class ldiv_t extends ffi.Struct {\n  @ffi.Long()\n  external int quot;\n\n  @ffi.Long()\n  external int rem;\n}\n\nfinal class lldiv_t extends ffi.Struct {\n  @ffi.LongLong()\n  external int quot;\n\n  @ffi.LongLong()\n  external int rem;\n}\n\ntypedef malloc_type_id_t = ffi.UnsignedLongLong;\ntypedef Dartmalloc_type_id_t = int;\n\nfinal class _malloc_zone_t extends ffi.Opaque {}\n\ntypedef malloc_zone_t = _malloc_zone_t;\ntypedef dev_t = __darwin_dev_t;\ntypedef __darwin_dev_t = __int32_t;\ntypedef mode_t = __darwin_mode_t;\ntypedef __darwin_mode_t = __uint16_t;\ntypedef __uint16_t = ffi.UnsignedShort;\ntypedef Dart__uint16_t = int;\ntypedef pthread_t = __darwin_pthread_t;\ntypedef __darwin_pthread_t = ffi.Pointer<_opaque_pthread_t>;\ntypedef stack_t = __darwin_sigaltstack;\n\nfinal class GoInterface extends ffi.Struct {\n  external ffi.Pointer<ffi.Void> t;\n\n  external ffi.Pointer<ffi.Void> v;\n}\n\nfinal class GoSlice extends ffi.Struct {\n  external ffi.Pointer<ffi.Void> data;\n\n  @GoInt()\n  external int len;\n\n  @GoInt()\n  external int cap;\n}\n\ntypedef GoInt = GoInt64;\ntypedef GoInt64 = ffi.LongLong;\ntypedef DartGoInt64 = int;\ntypedef GoUint8 = ffi.UnsignedChar;\ntypedef DartGoUint8 = int;\n\nconst int __has_safe_buffers = 1;\n\nconst int __DARWIN_ONLY_64_BIT_INO_T = 1;\n\nconst int __DARWIN_ONLY_UNIX_CONFORMANCE = 1;\n\nconst int __DARWIN_ONLY_VERS_1050 = 1;\n\nconst int __DARWIN_UNIX03 = 1;\n\nconst int __DARWIN_64_BIT_INO_T = 1;\n\nconst int __DARWIN_VERS_1050 = 1;\n\nconst int __DARWIN_NON_CANCELABLE = 0;\n\nconst String __DARWIN_SUF_EXTSN = '\\$DARWIN_EXTSN';\n\nconst int __DARWIN_C_ANSI = 4096;\n\nconst int __DARWIN_C_FULL = 900000;\n\nconst int __DARWIN_C_LEVEL = 900000;\n\nconst int __STDC_WANT_LIB_EXT1__ = 1;\n\nconst int __DARWIN_NO_LONG_LONG = 0;\n\nconst int _DARWIN_FEATURE_64_BIT_INODE = 1;\n\nconst int _DARWIN_FEATURE_ONLY_64_BIT_INODE = 1;\n\nconst int _DARWIN_FEATURE_ONLY_VERS_1050 = 1;\n\nconst int _DARWIN_FEATURE_ONLY_UNIX_CONFORMANCE = 1;\n\nconst int _DARWIN_FEATURE_UNIX_CONFORMANCE = 3;\n\nconst int __has_ptrcheck = 0;\n\nconst int __DARWIN_NULL = 0;\n\nconst int __PTHREAD_SIZE__ = 8176;\n\nconst int __PTHREAD_ATTR_SIZE__ = 56;\n\nconst int __PTHREAD_MUTEXATTR_SIZE__ = 8;\n\nconst int __PTHREAD_MUTEX_SIZE__ = 56;\n\nconst int __PTHREAD_CONDATTR_SIZE__ = 8;\n\nconst int __PTHREAD_COND_SIZE__ = 40;\n\nconst int __PTHREAD_ONCE_SIZE__ = 8;\n\nconst int __PTHREAD_RWLOCK_SIZE__ = 192;\n\nconst int __PTHREAD_RWLOCKATTR_SIZE__ = 16;\n\nconst int __DARWIN_WCHAR_MAX = 2147483647;\n\nconst int __DARWIN_WCHAR_MIN = -2147483648;\n\nconst int __DARWIN_WEOF = -1;\n\nconst int _FORTIFY_SOURCE = 2;\n\nconst int NULL = 0;\n\nconst int USER_ADDR_NULL = 0;\n\nconst int __API_TO_BE_DEPRECATED = 100000;\n\nconst int __API_TO_BE_DEPRECATED_MACOS = 100000;\n\nconst int __API_TO_BE_DEPRECATED_IOS = 100000;\n\nconst int __API_TO_BE_DEPRECATED_MACCATALYST = 100000;\n\nconst int __API_TO_BE_DEPRECATED_WATCHOS = 100000;\n\nconst int __API_TO_BE_DEPRECATED_TVOS = 100000;\n\nconst int __API_TO_BE_DEPRECATED_DRIVERKIT = 100000;\n\nconst int __API_TO_BE_DEPRECATED_VISIONOS = 100000;\n\nconst int __MAC_10_0 = 1000;\n\nconst int __MAC_10_1 = 1010;\n\nconst int __MAC_10_2 = 1020;\n\nconst int __MAC_10_3 = 1030;\n\nconst int __MAC_10_4 = 1040;\n\nconst int __MAC_10_5 = 1050;\n\nconst int __MAC_10_6 = 1060;\n\nconst int __MAC_10_7 = 1070;\n\nconst int __MAC_10_8 = 1080;\n\nconst int __MAC_10_9 = 1090;\n\nconst int __MAC_10_10 = 101000;\n\nconst int __MAC_10_10_2 = 101002;\n\nconst int __MAC_10_10_3 = 101003;\n\nconst int __MAC_10_11 = 101100;\n\nconst int __MAC_10_11_2 = 101102;\n\nconst int __MAC_10_11_3 = 101103;\n\nconst int __MAC_10_11_4 = 101104;\n\nconst int __MAC_10_12 = 101200;\n\nconst int __MAC_10_12_1 = 101201;\n\nconst int __MAC_10_12_2 = 101202;\n\nconst int __MAC_10_12_4 = 101204;\n\nconst int __MAC_10_13 = 101300;\n\nconst int __MAC_10_13_1 = 101301;\n\nconst int __MAC_10_13_2 = 101302;\n\nconst int __MAC_10_13_4 = 101304;\n\nconst int __MAC_10_14 = 101400;\n\nconst int __MAC_10_14_1 = 101401;\n\nconst int __MAC_10_14_4 = 101404;\n\nconst int __MAC_10_14_5 = 101405;\n\nconst int __MAC_10_14_6 = 101406;\n\nconst int __MAC_10_15 = 101500;\n\nconst int __MAC_10_15_1 = 101501;\n\nconst int __MAC_10_15_4 = 101504;\n\nconst int __MAC_10_16 = 101600;\n\nconst int __MAC_11_0 = 110000;\n\nconst int __MAC_11_1 = 110100;\n\nconst int __MAC_11_3 = 110300;\n\nconst int __MAC_11_4 = 110400;\n\nconst int __MAC_11_5 = 110500;\n\nconst int __MAC_11_6 = 110600;\n\nconst int __MAC_12_0 = 120000;\n\nconst int __MAC_12_1 = 120100;\n\nconst int __MAC_12_2 = 120200;\n\nconst int __MAC_12_3 = 120300;\n\nconst int __MAC_12_4 = 120400;\n\nconst int __MAC_12_5 = 120500;\n\nconst int __MAC_12_6 = 120600;\n\nconst int __MAC_12_7 = 120700;\n\nconst int __MAC_13_0 = 130000;\n\nconst int __MAC_13_1 = 130100;\n\nconst int __MAC_13_2 = 130200;\n\nconst int __MAC_13_3 = 130300;\n\nconst int __MAC_13_4 = 130400;\n\nconst int __MAC_13_5 = 130500;\n\nconst int __MAC_13_6 = 130600;\n\nconst int __MAC_14_0 = 140000;\n\nconst int __MAC_14_1 = 140100;\n\nconst int __MAC_14_2 = 140200;\n\nconst int __MAC_14_3 = 140300;\n\nconst int __MAC_14_4 = 140400;\n\nconst int __MAC_14_5 = 140500;\n\nconst int __IPHONE_2_0 = 20000;\n\nconst int __IPHONE_2_1 = 20100;\n\nconst int __IPHONE_2_2 = 20200;\n\nconst int __IPHONE_3_0 = 30000;\n\nconst int __IPHONE_3_1 = 30100;\n\nconst int __IPHONE_3_2 = 30200;\n\nconst int __IPHONE_4_0 = 40000;\n\nconst int __IPHONE_4_1 = 40100;\n\nconst int __IPHONE_4_2 = 40200;\n\nconst int __IPHONE_4_3 = 40300;\n\nconst int __IPHONE_5_0 = 50000;\n\nconst int __IPHONE_5_1 = 50100;\n\nconst int __IPHONE_6_0 = 60000;\n\nconst int __IPHONE_6_1 = 60100;\n\nconst int __IPHONE_7_0 = 70000;\n\nconst int __IPHONE_7_1 = 70100;\n\nconst int __IPHONE_8_0 = 80000;\n\nconst int __IPHONE_8_1 = 80100;\n\nconst int __IPHONE_8_2 = 80200;\n\nconst int __IPHONE_8_3 = 80300;\n\nconst int __IPHONE_8_4 = 80400;\n\nconst int __IPHONE_9_0 = 90000;\n\nconst int __IPHONE_9_1 = 90100;\n\nconst int __IPHONE_9_2 = 90200;\n\nconst int __IPHONE_9_3 = 90300;\n\nconst int __IPHONE_10_0 = 100000;\n\nconst int __IPHONE_10_1 = 100100;\n\nconst int __IPHONE_10_2 = 100200;\n\nconst int __IPHONE_10_3 = 100300;\n\nconst int __IPHONE_11_0 = 110000;\n\nconst int __IPHONE_11_1 = 110100;\n\nconst int __IPHONE_11_2 = 110200;\n\nconst int __IPHONE_11_3 = 110300;\n\nconst int __IPHONE_11_4 = 110400;\n\nconst int __IPHONE_12_0 = 120000;\n\nconst int __IPHONE_12_1 = 120100;\n\nconst int __IPHONE_12_2 = 120200;\n\nconst int __IPHONE_12_3 = 120300;\n\nconst int __IPHONE_12_4 = 120400;\n\nconst int __IPHONE_13_0 = 130000;\n\nconst int __IPHONE_13_1 = 130100;\n\nconst int __IPHONE_13_2 = 130200;\n\nconst int __IPHONE_13_3 = 130300;\n\nconst int __IPHONE_13_4 = 130400;\n\nconst int __IPHONE_13_5 = 130500;\n\nconst int __IPHONE_13_6 = 130600;\n\nconst int __IPHONE_13_7 = 130700;\n\nconst int __IPHONE_14_0 = 140000;\n\nconst int __IPHONE_14_1 = 140100;\n\nconst int __IPHONE_14_2 = 140200;\n\nconst int __IPHONE_14_3 = 140300;\n\nconst int __IPHONE_14_5 = 140500;\n\nconst int __IPHONE_14_4 = 140400;\n\nconst int __IPHONE_14_6 = 140600;\n\nconst int __IPHONE_14_7 = 140700;\n\nconst int __IPHONE_14_8 = 140800;\n\nconst int __IPHONE_15_0 = 150000;\n\nconst int __IPHONE_15_1 = 150100;\n\nconst int __IPHONE_15_2 = 150200;\n\nconst int __IPHONE_15_3 = 150300;\n\nconst int __IPHONE_15_4 = 150400;\n\nconst int __IPHONE_15_5 = 150500;\n\nconst int __IPHONE_15_6 = 150600;\n\nconst int __IPHONE_15_7 = 150700;\n\nconst int __IPHONE_15_8 = 150800;\n\nconst int __IPHONE_16_0 = 160000;\n\nconst int __IPHONE_16_1 = 160100;\n\nconst int __IPHONE_16_2 = 160200;\n\nconst int __IPHONE_16_3 = 160300;\n\nconst int __IPHONE_16_4 = 160400;\n\nconst int __IPHONE_16_5 = 160500;\n\nconst int __IPHONE_16_6 = 160600;\n\nconst int __IPHONE_16_7 = 160700;\n\nconst int __IPHONE_17_0 = 170000;\n\nconst int __IPHONE_17_1 = 170100;\n\nconst int __IPHONE_17_2 = 170200;\n\nconst int __IPHONE_17_3 = 170300;\n\nconst int __IPHONE_17_4 = 170400;\n\nconst int __IPHONE_17_5 = 170500;\n\nconst int __WATCHOS_1_0 = 10000;\n\nconst int __WATCHOS_2_0 = 20000;\n\nconst int __WATCHOS_2_1 = 20100;\n\nconst int __WATCHOS_2_2 = 20200;\n\nconst int __WATCHOS_3_0 = 30000;\n\nconst int __WATCHOS_3_1 = 30100;\n\nconst int __WATCHOS_3_1_1 = 30101;\n\nconst int __WATCHOS_3_2 = 30200;\n\nconst int __WATCHOS_4_0 = 40000;\n\nconst int __WATCHOS_4_1 = 40100;\n\nconst int __WATCHOS_4_2 = 40200;\n\nconst int __WATCHOS_4_3 = 40300;\n\nconst int __WATCHOS_5_0 = 50000;\n\nconst int __WATCHOS_5_1 = 50100;\n\nconst int __WATCHOS_5_2 = 50200;\n\nconst int __WATCHOS_5_3 = 50300;\n\nconst int __WATCHOS_6_0 = 60000;\n\nconst int __WATCHOS_6_1 = 60100;\n\nconst int __WATCHOS_6_2 = 60200;\n\nconst int __WATCHOS_7_0 = 70000;\n\nconst int __WATCHOS_7_1 = 70100;\n\nconst int __WATCHOS_7_2 = 70200;\n\nconst int __WATCHOS_7_3 = 70300;\n\nconst int __WATCHOS_7_4 = 70400;\n\nconst int __WATCHOS_7_5 = 70500;\n\nconst int __WATCHOS_7_6 = 70600;\n\nconst int __WATCHOS_8_0 = 80000;\n\nconst int __WATCHOS_8_1 = 80100;\n\nconst int __WATCHOS_8_3 = 80300;\n\nconst int __WATCHOS_8_4 = 80400;\n\nconst int __WATCHOS_8_5 = 80500;\n\nconst int __WATCHOS_8_6 = 80600;\n\nconst int __WATCHOS_8_7 = 80700;\n\nconst int __WATCHOS_8_8 = 80800;\n\nconst int __WATCHOS_9_0 = 90000;\n\nconst int __WATCHOS_9_1 = 90100;\n\nconst int __WATCHOS_9_2 = 90200;\n\nconst int __WATCHOS_9_3 = 90300;\n\nconst int __WATCHOS_9_4 = 90400;\n\nconst int __WATCHOS_9_5 = 90500;\n\nconst int __WATCHOS_9_6 = 90600;\n\nconst int __WATCHOS_10_0 = 100000;\n\nconst int __WATCHOS_10_1 = 100100;\n\nconst int __WATCHOS_10_2 = 100200;\n\nconst int __WATCHOS_10_3 = 100300;\n\nconst int __WATCHOS_10_4 = 100400;\n\nconst int __WATCHOS_10_5 = 100500;\n\nconst int __TVOS_9_0 = 90000;\n\nconst int __TVOS_9_1 = 90100;\n\nconst int __TVOS_9_2 = 90200;\n\nconst int __TVOS_10_0 = 100000;\n\nconst int __TVOS_10_0_1 = 100001;\n\nconst int __TVOS_10_1 = 100100;\n\nconst int __TVOS_10_2 = 100200;\n\nconst int __TVOS_11_0 = 110000;\n\nconst int __TVOS_11_1 = 110100;\n\nconst int __TVOS_11_2 = 110200;\n\nconst int __TVOS_11_3 = 110300;\n\nconst int __TVOS_11_4 = 110400;\n\nconst int __TVOS_12_0 = 120000;\n\nconst int __TVOS_12_1 = 120100;\n\nconst int __TVOS_12_2 = 120200;\n\nconst int __TVOS_12_3 = 120300;\n\nconst int __TVOS_12_4 = 120400;\n\nconst int __TVOS_13_0 = 130000;\n\nconst int __TVOS_13_2 = 130200;\n\nconst int __TVOS_13_3 = 130300;\n\nconst int __TVOS_13_4 = 130400;\n\nconst int __TVOS_14_0 = 140000;\n\nconst int __TVOS_14_1 = 140100;\n\nconst int __TVOS_14_2 = 140200;\n\nconst int __TVOS_14_3 = 140300;\n\nconst int __TVOS_14_5 = 140500;\n\nconst int __TVOS_14_6 = 140600;\n\nconst int __TVOS_14_7 = 140700;\n\nconst int __TVOS_15_0 = 150000;\n\nconst int __TVOS_15_1 = 150100;\n\nconst int __TVOS_15_2 = 150200;\n\nconst int __TVOS_15_3 = 150300;\n\nconst int __TVOS_15_4 = 150400;\n\nconst int __TVOS_15_5 = 150500;\n\nconst int __TVOS_15_6 = 150600;\n\nconst int __TVOS_16_0 = 160000;\n\nconst int __TVOS_16_1 = 160100;\n\nconst int __TVOS_16_2 = 160200;\n\nconst int __TVOS_16_3 = 160300;\n\nconst int __TVOS_16_4 = 160400;\n\nconst int __TVOS_16_5 = 160500;\n\nconst int __TVOS_16_6 = 160600;\n\nconst int __TVOS_17_0 = 170000;\n\nconst int __TVOS_17_1 = 170100;\n\nconst int __TVOS_17_2 = 170200;\n\nconst int __TVOS_17_3 = 170300;\n\nconst int __TVOS_17_4 = 170400;\n\nconst int __TVOS_17_5 = 170500;\n\nconst int __BRIDGEOS_2_0 = 20000;\n\nconst int __BRIDGEOS_3_0 = 30000;\n\nconst int __BRIDGEOS_3_1 = 30100;\n\nconst int __BRIDGEOS_3_4 = 30400;\n\nconst int __BRIDGEOS_4_0 = 40000;\n\nconst int __BRIDGEOS_4_1 = 40100;\n\nconst int __BRIDGEOS_5_0 = 50000;\n\nconst int __BRIDGEOS_5_1 = 50100;\n\nconst int __BRIDGEOS_5_3 = 50300;\n\nconst int __BRIDGEOS_6_0 = 60000;\n\nconst int __BRIDGEOS_6_2 = 60200;\n\nconst int __BRIDGEOS_6_4 = 60400;\n\nconst int __BRIDGEOS_6_5 = 60500;\n\nconst int __BRIDGEOS_6_6 = 60600;\n\nconst int __BRIDGEOS_7_0 = 70000;\n\nconst int __BRIDGEOS_7_1 = 70100;\n\nconst int __BRIDGEOS_7_2 = 70200;\n\nconst int __BRIDGEOS_7_3 = 70300;\n\nconst int __BRIDGEOS_7_4 = 70400;\n\nconst int __BRIDGEOS_7_6 = 70600;\n\nconst int __BRIDGEOS_8_0 = 80000;\n\nconst int __BRIDGEOS_8_1 = 80100;\n\nconst int __BRIDGEOS_8_2 = 80200;\n\nconst int __BRIDGEOS_8_3 = 80300;\n\nconst int __BRIDGEOS_8_4 = 80400;\n\nconst int __BRIDGEOS_8_5 = 80500;\n\nconst int __DRIVERKIT_19_0 = 190000;\n\nconst int __DRIVERKIT_20_0 = 200000;\n\nconst int __DRIVERKIT_21_0 = 210000;\n\nconst int __DRIVERKIT_22_0 = 220000;\n\nconst int __DRIVERKIT_22_4 = 220400;\n\nconst int __DRIVERKIT_22_5 = 220500;\n\nconst int __DRIVERKIT_22_6 = 220600;\n\nconst int __DRIVERKIT_23_0 = 230000;\n\nconst int __DRIVERKIT_23_1 = 230100;\n\nconst int __DRIVERKIT_23_2 = 230200;\n\nconst int __DRIVERKIT_23_3 = 230300;\n\nconst int __DRIVERKIT_23_4 = 230400;\n\nconst int __DRIVERKIT_23_5 = 230500;\n\nconst int __VISIONOS_1_0 = 10000;\n\nconst int __VISIONOS_1_1 = 10100;\n\nconst int __VISIONOS_1_2 = 10200;\n\nconst int MAC_OS_X_VERSION_10_0 = 1000;\n\nconst int MAC_OS_X_VERSION_10_1 = 1010;\n\nconst int MAC_OS_X_VERSION_10_2 = 1020;\n\nconst int MAC_OS_X_VERSION_10_3 = 1030;\n\nconst int MAC_OS_X_VERSION_10_4 = 1040;\n\nconst int MAC_OS_X_VERSION_10_5 = 1050;\n\nconst int MAC_OS_X_VERSION_10_6 = 1060;\n\nconst int MAC_OS_X_VERSION_10_7 = 1070;\n\nconst int MAC_OS_X_VERSION_10_8 = 1080;\n\nconst int MAC_OS_X_VERSION_10_9 = 1090;\n\nconst int MAC_OS_X_VERSION_10_10 = 101000;\n\nconst int MAC_OS_X_VERSION_10_10_2 = 101002;\n\nconst int MAC_OS_X_VERSION_10_10_3 = 101003;\n\nconst int MAC_OS_X_VERSION_10_11 = 101100;\n\nconst int MAC_OS_X_VERSION_10_11_2 = 101102;\n\nconst int MAC_OS_X_VERSION_10_11_3 = 101103;\n\nconst int MAC_OS_X_VERSION_10_11_4 = 101104;\n\nconst int MAC_OS_X_VERSION_10_12 = 101200;\n\nconst int MAC_OS_X_VERSION_10_12_1 = 101201;\n\nconst int MAC_OS_X_VERSION_10_12_2 = 101202;\n\nconst int MAC_OS_X_VERSION_10_12_4 = 101204;\n\nconst int MAC_OS_X_VERSION_10_13 = 101300;\n\nconst int MAC_OS_X_VERSION_10_13_1 = 101301;\n\nconst int MAC_OS_X_VERSION_10_13_2 = 101302;\n\nconst int MAC_OS_X_VERSION_10_13_4 = 101304;\n\nconst int MAC_OS_X_VERSION_10_14 = 101400;\n\nconst int MAC_OS_X_VERSION_10_14_1 = 101401;\n\nconst int MAC_OS_X_VERSION_10_14_4 = 101404;\n\nconst int MAC_OS_X_VERSION_10_14_5 = 101405;\n\nconst int MAC_OS_X_VERSION_10_14_6 = 101406;\n\nconst int MAC_OS_X_VERSION_10_15 = 101500;\n\nconst int MAC_OS_X_VERSION_10_15_1 = 101501;\n\nconst int MAC_OS_X_VERSION_10_15_4 = 101504;\n\nconst int MAC_OS_X_VERSION_10_16 = 101600;\n\nconst int MAC_OS_VERSION_11_0 = 110000;\n\nconst int MAC_OS_VERSION_11_1 = 110100;\n\nconst int MAC_OS_VERSION_11_3 = 110300;\n\nconst int MAC_OS_VERSION_11_4 = 110400;\n\nconst int MAC_OS_VERSION_11_5 = 110500;\n\nconst int MAC_OS_VERSION_11_6 = 110600;\n\nconst int MAC_OS_VERSION_12_0 = 120000;\n\nconst int MAC_OS_VERSION_12_1 = 120100;\n\nconst int MAC_OS_VERSION_12_2 = 120200;\n\nconst int MAC_OS_VERSION_12_3 = 120300;\n\nconst int MAC_OS_VERSION_12_4 = 120400;\n\nconst int MAC_OS_VERSION_12_5 = 120500;\n\nconst int MAC_OS_VERSION_12_6 = 120600;\n\nconst int MAC_OS_VERSION_12_7 = 120700;\n\nconst int MAC_OS_VERSION_13_0 = 130000;\n\nconst int MAC_OS_VERSION_13_1 = 130100;\n\nconst int MAC_OS_VERSION_13_2 = 130200;\n\nconst int MAC_OS_VERSION_13_3 = 130300;\n\nconst int MAC_OS_VERSION_13_4 = 130400;\n\nconst int MAC_OS_VERSION_13_5 = 130500;\n\nconst int MAC_OS_VERSION_13_6 = 130600;\n\nconst int MAC_OS_VERSION_14_0 = 140000;\n\nconst int MAC_OS_VERSION_14_1 = 140100;\n\nconst int MAC_OS_VERSION_14_2 = 140200;\n\nconst int MAC_OS_VERSION_14_3 = 140300;\n\nconst int MAC_OS_VERSION_14_4 = 140400;\n\nconst int MAC_OS_VERSION_14_5 = 140500;\n\nconst int __MAC_OS_X_VERSION_MIN_REQUIRED = 140000;\n\nconst int __MAC_OS_X_VERSION_MAX_ALLOWED = 140500;\n\nconst int __ENABLE_LEGACY_MAC_AVAILABILITY = 1;\n\nconst int __DARWIN_NSIG = 32;\n\nconst int NSIG = 32;\n\nconst int _ARM_SIGNAL_ = 1;\n\nconst int SIGHUP = 1;\n\nconst int SIGINT = 2;\n\nconst int SIGQUIT = 3;\n\nconst int SIGILL = 4;\n\nconst int SIGTRAP = 5;\n\nconst int SIGABRT = 6;\n\nconst int SIGIOT = 6;\n\nconst int SIGEMT = 7;\n\nconst int SIGFPE = 8;\n\nconst int SIGKILL = 9;\n\nconst int SIGBUS = 10;\n\nconst int SIGSEGV = 11;\n\nconst int SIGSYS = 12;\n\nconst int SIGPIPE = 13;\n\nconst int SIGALRM = 14;\n\nconst int SIGTERM = 15;\n\nconst int SIGURG = 16;\n\nconst int SIGSTOP = 17;\n\nconst int SIGTSTP = 18;\n\nconst int SIGCONT = 19;\n\nconst int SIGCHLD = 20;\n\nconst int SIGTTIN = 21;\n\nconst int SIGTTOU = 22;\n\nconst int SIGIO = 23;\n\nconst int SIGXCPU = 24;\n\nconst int SIGXFSZ = 25;\n\nconst int SIGVTALRM = 26;\n\nconst int SIGPROF = 27;\n\nconst int SIGWINCH = 28;\n\nconst int SIGINFO = 29;\n\nconst int SIGUSR1 = 30;\n\nconst int SIGUSR2 = 31;\n\nconst int __DARWIN_OPAQUE_ARM_THREAD_STATE64 = 0;\n\nconst int SIGEV_NONE = 0;\n\nconst int SIGEV_SIGNAL = 1;\n\nconst int SIGEV_THREAD = 3;\n\nconst int ILL_NOOP = 0;\n\nconst int ILL_ILLOPC = 1;\n\nconst int ILL_ILLTRP = 2;\n\nconst int ILL_PRVOPC = 3;\n\nconst int ILL_ILLOPN = 4;\n\nconst int ILL_ILLADR = 5;\n\nconst int ILL_PRVREG = 6;\n\nconst int ILL_COPROC = 7;\n\nconst int ILL_BADSTK = 8;\n\nconst int FPE_NOOP = 0;\n\nconst int FPE_FLTDIV = 1;\n\nconst int FPE_FLTOVF = 2;\n\nconst int FPE_FLTUND = 3;\n\nconst int FPE_FLTRES = 4;\n\nconst int FPE_FLTINV = 5;\n\nconst int FPE_FLTSUB = 6;\n\nconst int FPE_INTDIV = 7;\n\nconst int FPE_INTOVF = 8;\n\nconst int SEGV_NOOP = 0;\n\nconst int SEGV_MAPERR = 1;\n\nconst int SEGV_ACCERR = 2;\n\nconst int BUS_NOOP = 0;\n\nconst int BUS_ADRALN = 1;\n\nconst int BUS_ADRERR = 2;\n\nconst int BUS_OBJERR = 3;\n\nconst int TRAP_BRKPT = 1;\n\nconst int TRAP_TRACE = 2;\n\nconst int CLD_NOOP = 0;\n\nconst int CLD_EXITED = 1;\n\nconst int CLD_KILLED = 2;\n\nconst int CLD_DUMPED = 3;\n\nconst int CLD_TRAPPED = 4;\n\nconst int CLD_STOPPED = 5;\n\nconst int CLD_CONTINUED = 6;\n\nconst int POLL_IN = 1;\n\nconst int POLL_OUT = 2;\n\nconst int POLL_MSG = 3;\n\nconst int POLL_ERR = 4;\n\nconst int POLL_PRI = 5;\n\nconst int POLL_HUP = 6;\n\nconst int SA_ONSTACK = 1;\n\nconst int SA_RESTART = 2;\n\nconst int SA_RESETHAND = 4;\n\nconst int SA_NOCLDSTOP = 8;\n\nconst int SA_NODEFER = 16;\n\nconst int SA_NOCLDWAIT = 32;\n\nconst int SA_SIGINFO = 64;\n\nconst int SA_USERTRAMP = 256;\n\nconst int SA_64REGSET = 512;\n\nconst int SA_USERSPACE_MASK = 127;\n\nconst int SIG_BLOCK = 1;\n\nconst int SIG_UNBLOCK = 2;\n\nconst int SIG_SETMASK = 3;\n\nconst int SI_USER = 65537;\n\nconst int SI_QUEUE = 65538;\n\nconst int SI_TIMER = 65539;\n\nconst int SI_ASYNCIO = 65540;\n\nconst int SI_MESGQ = 65541;\n\nconst int SS_ONSTACK = 1;\n\nconst int SS_DISABLE = 4;\n\nconst int MINSIGSTKSZ = 32768;\n\nconst int SIGSTKSZ = 131072;\n\nconst int SV_ONSTACK = 1;\n\nconst int SV_INTERRUPT = 2;\n\nconst int SV_RESETHAND = 4;\n\nconst int SV_NODEFER = 16;\n\nconst int SV_NOCLDSTOP = 8;\n\nconst int SV_SIGINFO = 64;\n\nconst int __WORDSIZE = 64;\n\nconst int INT8_MAX = 127;\n\nconst int INT16_MAX = 32767;\n\nconst int INT32_MAX = 2147483647;\n\nconst int INT64_MAX = 9223372036854775807;\n\nconst int INT8_MIN = -128;\n\nconst int INT16_MIN = -32768;\n\nconst int INT32_MIN = -2147483648;\n\nconst int INT64_MIN = -9223372036854775808;\n\nconst int UINT8_MAX = 255;\n\nconst int UINT16_MAX = 65535;\n\nconst int UINT32_MAX = 4294967295;\n\nconst int UINT64_MAX = -1;\n\nconst int INT_LEAST8_MIN = -128;\n\nconst int INT_LEAST16_MIN = -32768;\n\nconst int INT_LEAST32_MIN = -2147483648;\n\nconst int INT_LEAST64_MIN = -9223372036854775808;\n\nconst int INT_LEAST8_MAX = 127;\n\nconst int INT_LEAST16_MAX = 32767;\n\nconst int INT_LEAST32_MAX = 2147483647;\n\nconst int INT_LEAST64_MAX = 9223372036854775807;\n\nconst int UINT_LEAST8_MAX = 255;\n\nconst int UINT_LEAST16_MAX = 65535;\n\nconst int UINT_LEAST32_MAX = 4294967295;\n\nconst int UINT_LEAST64_MAX = -1;\n\nconst int INT_FAST8_MIN = -128;\n\nconst int INT_FAST16_MIN = -32768;\n\nconst int INT_FAST32_MIN = -2147483648;\n\nconst int INT_FAST64_MIN = -9223372036854775808;\n\nconst int INT_FAST8_MAX = 127;\n\nconst int INT_FAST16_MAX = 32767;\n\nconst int INT_FAST32_MAX = 2147483647;\n\nconst int INT_FAST64_MAX = 9223372036854775807;\n\nconst int UINT_FAST8_MAX = 255;\n\nconst int UINT_FAST16_MAX = 65535;\n\nconst int UINT_FAST32_MAX = 4294967295;\n\nconst int UINT_FAST64_MAX = -1;\n\nconst int INTPTR_MAX = 9223372036854775807;\n\nconst int INTPTR_MIN = -9223372036854775808;\n\nconst int UINTPTR_MAX = -1;\n\nconst int INTMAX_MAX = 9223372036854775807;\n\nconst int UINTMAX_MAX = -1;\n\nconst int INTMAX_MIN = -9223372036854775808;\n\nconst int PTRDIFF_MIN = -9223372036854775808;\n\nconst int PTRDIFF_MAX = 9223372036854775807;\n\nconst int SIZE_MAX = -1;\n\nconst int RSIZE_MAX = 9223372036854775807;\n\nconst int WCHAR_MAX = 2147483647;\n\nconst int WCHAR_MIN = -2147483648;\n\nconst int WINT_MIN = -2147483648;\n\nconst int WINT_MAX = 2147483647;\n\nconst int SIG_ATOMIC_MIN = -2147483648;\n\nconst int SIG_ATOMIC_MAX = 2147483647;\n\nconst int PRIO_PROCESS = 0;\n\nconst int PRIO_PGRP = 1;\n\nconst int PRIO_USER = 2;\n\nconst int PRIO_DARWIN_THREAD = 3;\n\nconst int PRIO_DARWIN_PROCESS = 4;\n\nconst int PRIO_MIN = -20;\n\nconst int PRIO_MAX = 20;\n\nconst int PRIO_DARWIN_BG = 4096;\n\nconst int PRIO_DARWIN_NONUI = 4097;\n\nconst int RUSAGE_SELF = 0;\n\nconst int RUSAGE_CHILDREN = -1;\n\nconst int RUSAGE_INFO_V0 = 0;\n\nconst int RUSAGE_INFO_V1 = 1;\n\nconst int RUSAGE_INFO_V2 = 2;\n\nconst int RUSAGE_INFO_V3 = 3;\n\nconst int RUSAGE_INFO_V4 = 4;\n\nconst int RUSAGE_INFO_V5 = 5;\n\nconst int RUSAGE_INFO_V6 = 6;\n\nconst int RUSAGE_INFO_CURRENT = 6;\n\nconst int RU_PROC_RUNS_RESLIDE = 1;\n\nconst int RLIM_INFINITY = 9223372036854775807;\n\nconst int RLIM_SAVED_MAX = 9223372036854775807;\n\nconst int RLIM_SAVED_CUR = 9223372036854775807;\n\nconst int RLIMIT_CPU = 0;\n\nconst int RLIMIT_FSIZE = 1;\n\nconst int RLIMIT_DATA = 2;\n\nconst int RLIMIT_STACK = 3;\n\nconst int RLIMIT_CORE = 4;\n\nconst int RLIMIT_AS = 5;\n\nconst int RLIMIT_RSS = 5;\n\nconst int RLIMIT_MEMLOCK = 6;\n\nconst int RLIMIT_NPROC = 7;\n\nconst int RLIMIT_NOFILE = 8;\n\nconst int RLIM_NLIMITS = 9;\n\nconst int _RLIMIT_POSIX_FLAG = 4096;\n\nconst int RLIMIT_WAKEUPS_MONITOR = 1;\n\nconst int RLIMIT_CPU_USAGE_MONITOR = 2;\n\nconst int RLIMIT_THREAD_CPULIMITS = 3;\n\nconst int RLIMIT_FOOTPRINT_INTERVAL = 4;\n\nconst int WAKEMON_ENABLE = 1;\n\nconst int WAKEMON_DISABLE = 2;\n\nconst int WAKEMON_GET_PARAMS = 4;\n\nconst int WAKEMON_SET_DEFAULTS = 8;\n\nconst int WAKEMON_MAKE_FATAL = 16;\n\nconst int CPUMON_MAKE_FATAL = 4096;\n\nconst int FOOTPRINT_INTERVAL_RESET = 1;\n\nconst int IOPOL_TYPE_DISK = 0;\n\nconst int IOPOL_TYPE_VFS_ATIME_UPDATES = 2;\n\nconst int IOPOL_TYPE_VFS_MATERIALIZE_DATALESS_FILES = 3;\n\nconst int IOPOL_TYPE_VFS_STATFS_NO_DATA_VOLUME = 4;\n\nconst int IOPOL_TYPE_VFS_TRIGGER_RESOLVE = 5;\n\nconst int IOPOL_TYPE_VFS_IGNORE_CONTENT_PROTECTION = 6;\n\nconst int IOPOL_TYPE_VFS_IGNORE_PERMISSIONS = 7;\n\nconst int IOPOL_TYPE_VFS_SKIP_MTIME_UPDATE = 8;\n\nconst int IOPOL_TYPE_VFS_ALLOW_LOW_SPACE_WRITES = 9;\n\nconst int IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY = 10;\n\nconst int IOPOL_SCOPE_PROCESS = 0;\n\nconst int IOPOL_SCOPE_THREAD = 1;\n\nconst int IOPOL_SCOPE_DARWIN_BG = 2;\n\nconst int IOPOL_DEFAULT = 0;\n\nconst int IOPOL_IMPORTANT = 1;\n\nconst int IOPOL_PASSIVE = 2;\n\nconst int IOPOL_THROTTLE = 3;\n\nconst int IOPOL_UTILITY = 4;\n\nconst int IOPOL_STANDARD = 5;\n\nconst int IOPOL_APPLICATION = 5;\n\nconst int IOPOL_NORMAL = 1;\n\nconst int IOPOL_ATIME_UPDATES_DEFAULT = 0;\n\nconst int IOPOL_ATIME_UPDATES_OFF = 1;\n\nconst int IOPOL_MATERIALIZE_DATALESS_FILES_DEFAULT = 0;\n\nconst int IOPOL_MATERIALIZE_DATALESS_FILES_OFF = 1;\n\nconst int IOPOL_MATERIALIZE_DATALESS_FILES_ON = 2;\n\nconst int IOPOL_VFS_STATFS_NO_DATA_VOLUME_DEFAULT = 0;\n\nconst int IOPOL_VFS_STATFS_FORCE_NO_DATA_VOLUME = 1;\n\nconst int IOPOL_VFS_TRIGGER_RESOLVE_DEFAULT = 0;\n\nconst int IOPOL_VFS_TRIGGER_RESOLVE_OFF = 1;\n\nconst int IOPOL_VFS_CONTENT_PROTECTION_DEFAULT = 0;\n\nconst int IOPOL_VFS_CONTENT_PROTECTION_IGNORE = 1;\n\nconst int IOPOL_VFS_IGNORE_PERMISSIONS_OFF = 0;\n\nconst int IOPOL_VFS_IGNORE_PERMISSIONS_ON = 1;\n\nconst int IOPOL_VFS_SKIP_MTIME_UPDATE_OFF = 0;\n\nconst int IOPOL_VFS_SKIP_MTIME_UPDATE_ON = 1;\n\nconst int IOPOL_VFS_ALLOW_LOW_SPACE_WRITES_OFF = 0;\n\nconst int IOPOL_VFS_ALLOW_LOW_SPACE_WRITES_ON = 1;\n\nconst int IOPOL_VFS_DISALLOW_RW_FOR_O_EVTONLY_DEFAULT = 0;\n\nconst int IOPOL_VFS_DISALLOW_RW_FOR_O_EVTONLY_ON = 1;\n\nconst int IOPOL_VFS_NOCACHE_WRITE_FS_BLKSIZE_DEFAULT = 0;\n\nconst int IOPOL_VFS_NOCACHE_WRITE_FS_BLKSIZE_ON = 1;\n\nconst int WNOHANG = 1;\n\nconst int WUNTRACED = 2;\n\nconst int WCOREFLAG = 128;\n\nconst int _WSTOPPED = 127;\n\nconst int WEXITED = 4;\n\nconst int WSTOPPED = 8;\n\nconst int WCONTINUED = 16;\n\nconst int WNOWAIT = 32;\n\nconst int WAIT_ANY = -1;\n\nconst int WAIT_MYPGRP = 0;\n\nconst int _QUAD_HIGHWORD = 1;\n\nconst int _QUAD_LOWWORD = 0;\n\nconst int __DARWIN_LITTLE_ENDIAN = 1234;\n\nconst int __DARWIN_BIG_ENDIAN = 4321;\n\nconst int __DARWIN_PDP_ENDIAN = 3412;\n\nconst int __DARWIN_BYTE_ORDER = 1234;\n\nconst int LITTLE_ENDIAN = 1234;\n\nconst int BIG_ENDIAN = 4321;\n\nconst int PDP_ENDIAN = 3412;\n\nconst int BYTE_ORDER = 1234;\n\nconst int EXIT_FAILURE = 1;\n\nconst int EXIT_SUCCESS = 0;\n\nconst int RAND_MAX = 2147483647;\n"
  },
  {
    "path": "lib/hiddifycore/core_interface/core_interface.dart",
    "content": "import 'package:hiddify/core/model/directories.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore_service.pbgrpc.dart';\nimport 'package:hiddify/singbox/model/core_status.dart';\n\nclass CoreInterface {\n  late CoreClient fgClient;\n  late CoreClient bgClient;\n\n  Future<String> setup(Directories directories, bool debug, int mode) async {\n    return \"\";\n  }\n\n  Future<CoreStatus> setupBackground(String path, String name) async {\n    return const CoreStarted();\n  }\n\n  Future<bool> restart(String path, String name) async {\n    return false;\n  }\n\n  Future<bool> stop() async {\n    return false;\n  }\n\n  Future<bool> isBgClientAvailable() async {\n    return true;\n  }\n\n  bool isSingleChannel() {\n    // return true;\n    return fgClient == bgClient;\n  }\n\n  Future<bool> resetTunnel() async {\n    return false;\n  }\n\n  Future<bool> isActiveFg() async {\n    return true;\n  }\n\n  Future<bool> isActiveBg() async {\n    return true;\n  }\n\n  bool isInitialized() {\n    try {\n      bgClient; // touch it\n      return true;\n    } catch (_) {\n      return false;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/hiddifycore/core_interface/core_interface_desktop.dart",
    "content": "import 'dart:ffi';\nimport 'dart:io';\nimport 'dart:math';\n\nimport 'package:ffi/ffi.dart';\nimport 'package:grpc/grpc.dart';\nimport 'package:hiddify/core/model/directories.dart';\nimport 'package:hiddify/gen/hiddify_core_generated_bindings.dart';\nimport 'package:hiddify/hiddifycore/core_interface/core_interface.dart';\nimport 'package:hiddify/hiddifycore/core_interface/mtls_channel_cred.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore_service.pbgrpc.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hello/hello.pb.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hello/hello_service.pbgrpc.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\n\nimport 'package:loggy/loggy.dart';\n\nimport 'package:path/path.dart' as p;\n\nfinal _logger = Loggy('HiddifyCoreFFI');\ntypedef StopFunc = Pointer<Utf8> Function();\ntypedef StopFuncDart = Pointer<Utf8> Function();\n\nclass CoreInterfaceDesktop extends CoreInterface with InfraLogger {\n  static final HiddifyCoreNativeLibrary _box = _gen();\n\n  static HiddifyCoreNativeLibrary _gen() {\n    String fullPath = \"\";\n    if (Platform.environment.containsKey('FLUTTER_TEST')) {\n      fullPath = \"hiddify-core\";\n    }\n    if (Platform.isWindows) {\n      fullPath = p.join(fullPath, \"hiddify-core.dll\");\n    } else if (Platform.isMacOS) {\n      fullPath = p.join(fullPath, \"hiddify-core.dylib\");\n    } else {\n      fullPath = p.join(fullPath, \"hiddify-core.so\");\n    }\n\n    _logger.debug('hiddify-core native libs path: \"$fullPath\"');\n    final lib = DynamicLibrary.open(fullPath);\n    // final stopFunc = lib.lookup<NativeFunction<StopFunc>>('stop').asFunction<StopFunc>();\n    // final errPtr2 = stopFunc();\n    // final err = errPtr2.cast<Utf8>().toDartString();\n\n    return HiddifyCoreNativeLibrary(lib);\n  }\n\n  Future<bool> isMusl() async {\n    try {\n      final result = await Process.run('ldd', ['--version']);\n      return result.stdout.toString().toLowerCase().contains('musl');\n    } catch (_) {\n      return false;\n    }\n  }\n\n  final port = 17078;\n  static String generateRandomPassword(int length) {\n    const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n    final random = Random();\n    return List.generate(length, (_) => characters[random.nextInt(characters.length)]).join();\n  }\n\n  static final String secret = generateRandomPassword(100);\n\n  @override\n  Future<String> setup(Directories directories, bool debug, int mode) async {\n    // Generate a random password for the grpc service\n    // final errPtr2 = _box.stop();\n    // final err = errPtr2.cast<Utf8>().toDartString();\n    // throw Exception('stop: $err');\n    const channelOption = ChannelCredentials.insecure();\n    final helloClient = HelloClient(\n      ClientChannel(\n        '127.0.0.1',\n        port: port,\n        options: const ChannelOptions(credentials: channelOption),\n      ),\n    );\n\n    try {\n      await helloClient.sayHello(HelloRequest(name: \"test\"));\n      loggy.info(\"core is already started!\");\n    } catch (e) {\n      //core is not started yet\n\n      final errPtr = _box.setup(\n        directories.baseDir.path.toNativeUtf8().cast(),\n        directories.workingDir.path.toNativeUtf8().cast(),\n        directories.tempDir.path.toNativeUtf8().cast(),\n        SetupMode.GRPC_NORMAL_INSECURE.value,\n        \"127.0.0.1:$port\".toNativeUtf8().cast(),\n        secret.toNativeUtf8().cast(),\n        0,\n        debug ? 1 : 0,\n      );\n      final err = errPtr.cast<Utf8>().toDartString();\n\n      if (err.isNotEmpty) {\n        return err;\n      }\n      final res = await helloClient.sayHello(HelloRequest(name: \"test\"));\n      loggy.info(res.toString());\n    }\n    bgClient = fgClient = CoreClient(\n      ClientChannel(\n        'localhost',\n        port: port,\n        options: const ChannelOptions(\n          credentials: ChannelCredentials.insecure(),\n          // credentials: ChannelCredentials.secure(\n          //   password: secret,\n          //   onBadCertificate: (certificate, host) => true,\n          // ),\n        ),\n      ),\n    );\n\n    return \"\";\n  }\n\n  @override\n  Future<bool> restart(String path, String name) async {\n    return false;\n  }\n\n  @override\n  Future<bool> stop() async {\n    return false;\n  }\n}\n"
  },
  {
    "path": "lib/hiddifycore/core_interface/core_interface_mobile.dart",
    "content": "import 'dart:async';\nimport 'dart:io';\n\nimport 'package:basic_utils/basic_utils.dart';\nimport 'package:flutter/services.dart';\nimport 'package:grpc/grpc.dart';\nimport 'package:hiddify/core/model/directories.dart';\nimport 'package:hiddify/core/utils/laststeam.dart';\nimport 'package:hiddify/hiddifycore/core_interface/core_interface.dart';\nimport 'package:hiddify/hiddifycore/core_interface/mtls_channel_cred.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore_service.pbgrpc.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hello/hello.pb.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hello/hello_service.pbgrpc.dart';\nimport 'package:hiddify/singbox/model/core_status.dart';\n\nimport 'package:hiddify/utils/utils.dart';\nimport 'package:loggy/loggy.dart';\nimport 'package:rxdart/rxdart.dart';\n\nfinal _logger = Loggy('FFIHiddifyCoreService');\n\nclass CoreInterfaceMobile extends CoreInterface with InfraLogger {\n  static const channelPrefix = \"com.hiddify.app\";\n  static const methodChannel = MethodChannel(\"$channelPrefix/method\");\n  static const statusChannel = EventChannel(\"$channelPrefix/service.status\", JSONMethodCodec());\n  static const alertsChannel = EventChannel(\"$channelPrefix/service.alerts\", JSONMethodCodec());\n\n  late Uint8List serverPublicKey;\n  static final cert = CryptoUtils.generateEcKeyPair();\n\n  static const portBack = 17079;\n  static const portFront = 17078;\n\n  bool _isBgClientAvailable = false;\n  bool _debug = false;\n\n  late LastStream<CoreStatus> _status;\n  @override\n  Future<String> setup(Directories directories, bool debug, int mode) async {\n    final channelOption = [1, 2].contains(mode)\n        ? MTLSChannelCredentials(serverPublicKey: serverPublicKey, clientKey: cert)\n        : const ChannelCredentials.insecure();\n    _debug = debug;\n    final helloClient = HelloClient(\n      ClientChannel(\n        '127.0.0.1',\n        port: portFront,\n        options: ChannelOptions(credentials: channelOption),\n      ),\n    );\n    final status = statusChannel.receiveBroadcastStream().map(CoreStatus.fromEvent);\n    final alerts = alertsChannel.receiveBroadcastStream().map(CoreStatus.fromEvent);\n\n    _status = LastStream(ValueConnectableStream(Rx.merge([status, alerts])).autoConnect());\n    try {\n      await helloClient.sayHello(HelloRequest(name: \"test\"));\n      loggy.info(\"core is already started!\");\n    } catch (e) {\n      //core is not started yet\n\n      await methodChannel.invokeMethod(\"setup\", {\n        \"baseDir\": directories.baseDir.path,\n        \"workingDir\": directories.workingDir.path,\n        \"tempDir\": directories.tempDir.path,\n        \"grpcPort\": portFront,\n        \"mode\": mode,\n        \"debug\": debug,\n      });\n      final res = await helloClient.sayHello(HelloRequest(name: \"test\"));\n      loggy.info(res.toString());\n    }\n\n    // serverPublicKey = await methodChannel.invokeMethod<Uint8List>(\"get_grpc_server_public_key\") ?? Uint8List.fromList([]);\n    // await methodChannel.invokeMethod(\n    //   \"add_grpc_client_public_key\",\n    //   {\n    //     \"clientPublicKey\": ascii.encode(CryptoUtils.encodeEcPublicKeyToPem(cert.publicKey as ECPublicKey)),\n    //   },\n    // );\n    // serverPublicKey = X509Utils.x509CertificateFromPem(String.fromCharCodes(serverPublicKey));\n    // var chanelOption = ChannelOptions(\n    //   credentials: MTLSChannelCredentials(serverPublicKey: serverPublicKey, clientPrivateKey: cert.privateKey as ECPrivateKey),\n    // );\n    fgClient = CoreClient(\n      ClientChannel(\n        '127.0.0.1',\n        port: portFront,\n        options: ChannelOptions(credentials: channelOption),\n      ),\n    );\n\n    bgClient = CoreClient(\n      ClientChannel(\n        '127.0.0.1',\n        port: portBack,\n        options: ChannelOptions(credentials: channelOption),\n      ),\n    );\n    // await start(\"/sdcard/Android/data/app.hiddify.com/files/configs/cdc633e9-8cfc-4a67-948d-009f779a5c91.json\", \"hiddify\");\n    return \"\";\n  }\n\n  @override\n  Future<CoreStatus> setupBackground(String path, String name) async {\n    // if (!await waitUntilPort(portBack, false, stop)) return const CoreStatus.stopped(alert: CoreAlert.createService);\n    if (!await stop()) return const CoreStatus.stopped(alert: CoreAlert.createService);\n    _status.clean();\n    await methodChannel.invokeMethod(\"start\", {\n      \"path\": path,\n      \"name\": name,\n      \"grpcPort\": portBack,\n      \"startBg\": true,\n      \"debug\": _debug,\n    });\n\n    _isBgClientAvailable = true;\n    loggy.info(\"Waiting for starting core\");\n    for (var i = 0; i < 20; i++) {\n      try {\n        final res = await _status.get(timeout: const Duration(seconds: 1));\n\n        switch (res) {\n          case CoreStarted():\n            break;\n          case CoreStopped():\n            if (res.alert != null) {\n              return res;\n            }\n\n          case CoreStopping():\n          // return res;\n          case CoreStarting():\n        }\n        await Future.delayed(const Duration(milliseconds: 200));\n      } on TimeoutException {\n        // just retry\n      }\n    }\n    loggy.info(\"Waiting for starting core finished\");\n\n    if (!await waitUntilPort(portBack, true, null, maxTry: 10)) {\n      await stopMethodChannel();\n      return const CoreStatus.stopped(alert: CoreAlert.startService, message: \"starting background core...\");\n    }\n    return const CoreStarted();\n  }\n\n  @override\n  Future<bool> stop() async {\n    await stopMethodChannel();\n    if (!await waitUntilPort(portBack, false, null, maxTry: 10)) {\n      return false;\n    }\n\n    _isBgClientAvailable = false;\n    return true;\n  }\n\n  Future stopMethodChannel() async {\n    await methodChannel.invokeMethod(\"stop\");\n  }\n\n  @override\n  Future<bool> isBgClientAvailable() async {\n    return _isBgClientAvailable;\n  }\n\n  @override\n  Future<bool> resetTunnel() async {\n    await methodChannel.invokeMethod(\"reset\");\n    return true;\n  }\n\n  @override\n  Future<bool> isActiveFg() async {\n    return await isPortOpen(\"127.0.0.1\", portFront);\n  }\n\n  @override\n  Future<bool> isActiveBg() async {\n    return await isPortOpen(\"127.0.0.1\", portBack);\n  }\n}\n\nFuture<bool> waitUntilPort(\n  int portNumber,\n  bool isOpen,\n  Future Function()? callFunctionAfterEachFail, {\n  int maxTry = 10,\n}) async {\n  for (var i = 0; i < maxTry; i++) {\n    if (await isPortOpen(\"127.0.0.1\", portNumber) == isOpen) {\n      return true;\n    }\n    if (callFunctionAfterEachFail != null) {\n      await callFunctionAfterEachFail();\n    }\n\n    await Future.delayed(const Duration(milliseconds: 200));\n  }\n  return false;\n}\n\nFuture<bool> isPortOpen(String host, int port, {Duration timeout = const Duration(milliseconds: 300)}) async {\n  try {\n    final socket = await Socket.connect(host, port, timeout: timeout);\n    await socket.close();\n    return true;\n  } on SocketException catch (_) {\n    return false;\n  } catch (_) {\n    return false;\n  }\n}\n"
  },
  {
    "path": "lib/hiddifycore/core_interface/core_interface_wrapper.dart",
    "content": "import 'dart:io';\n\nimport 'package:hiddify/hiddifycore/core_interface/core_interface.dart';\nimport 'package:hiddify/hiddifycore/core_interface/core_interface_desktop.dart';\nimport 'package:hiddify/hiddifycore/core_interface/core_interface_mobile.dart';\n\nCoreInterface getCoreInterface() {\n  if (Platform.isAndroid || Platform.isIOS) {\n    return CoreInterfaceMobile();\n  }\n  return CoreInterfaceDesktop();\n}\n"
  },
  {
    "path": "lib/hiddifycore/core_interface/core_interface_wrapper_stub.dart",
    "content": "import 'package:hiddify/hiddifycore/core_interface/core_interface.dart';\n\nCoreInterface getCoreInterface() {\n  return CoreInterface();\n}\n"
  },
  {
    "path": "lib/hiddifycore/core_interface/mtls_channel_cred.dart",
    "content": "import 'dart:io';\nimport 'dart:typed_data';\n\nimport 'package:basic_utils/basic_utils.dart';\nimport 'package:grpc/grpc.dart';\n\nclass MTLSChannelCredentials extends ChannelCredentials {\n  final SecurityContext ctx = SecurityContext(withTrustedRoots: false);\n\n  MTLSChannelCredentials({\n    required Uint8List serverPublicKey,\n    required AsymmetricKeyPair<PublicKey, PrivateKey> clientKey,\n  }) : super.secure() {\n    // Ensure server public key is in PEM format\n    final serverPublicKeyPem = String.fromCharCodes(serverPublicKey);\n    if (!serverPublicKeyPem.contains('-----BEGIN CERTIFICATE-----')) {\n      throw ArgumentError('Server public key must be in PEM format.');\n    }\n    // Set the server's public key as trusted\n    ctx.setTrustedCertificatesBytes(serverPublicKey);\n\n    // Convert the client's private key to PEM format\n    String privateKeyPem;\n    if (clientKey.privateKey is ECPrivateKey) {\n      privateKeyPem = CryptoUtils.encodeEcPrivateKeyToPem(clientKey.privateKey as ECPrivateKey);\n    } else if (clientKey.privateKey is RSAPrivateKey) {\n      privateKeyPem = CryptoUtils.encodeRSAPrivateKeyToPem(clientKey.privateKey as RSAPrivateKey);\n    } else {\n      throw ArgumentError('Unsupported private key type.');\n    }\n    ctx.usePrivateKeyBytes(Uint8List.fromList(privateKeyPem.codeUnits));\n\n    final cert = X509Utils.generateSelfSignedCertificate(clientKey.privateKey, 'CN=Client', 365);\n\n    ctx.useCertificateChainBytes(Uint8List.fromList(cert.codeUnits));\n  }\n\n  @override\n  SecurityContext get securityContext => ctx;\n\n  @override\n  bool get isSecure => true;\n}\n"
  },
  {
    "path": "lib/hiddifycore/generated/extension/extension.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: extension/extension.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nimport '../v2/hcommon/common.pbenum.dart' as $1;\nimport 'extension.pbenum.dart';\n\nexport 'extension.pbenum.dart';\n\nclass ExtensionActionResult extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ExtensionActionResult', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extension'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extensionId')\n    ..e<$1.ResponseCode>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: $1.ResponseCode.OK, valueOf: $1.ResponseCode.valueOf, enumValues: $1.ResponseCode.values)\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message')\n    ..hasRequiredFields = false\n  ;\n\n  ExtensionActionResult._() : super();\n  factory ExtensionActionResult({\n    $core.String? extensionId,\n    $1.ResponseCode? code,\n    $core.String? message,\n  }) {\n    final _result = create();\n    if (extensionId != null) {\n      _result.extensionId = extensionId;\n    }\n    if (code != null) {\n      _result.code = code;\n    }\n    if (message != null) {\n      _result.message = message;\n    }\n    return _result;\n  }\n  factory ExtensionActionResult.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ExtensionActionResult.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ExtensionActionResult clone() => ExtensionActionResult()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ExtensionActionResult copyWith(void Function(ExtensionActionResult) updates) => super.copyWith((message) => updates(message as ExtensionActionResult)) as ExtensionActionResult; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ExtensionActionResult create() => ExtensionActionResult._();\n  ExtensionActionResult createEmptyInstance() => create();\n  static $pb.PbList<ExtensionActionResult> createRepeated() => $pb.PbList<ExtensionActionResult>();\n  @$core.pragma('dart2js:noInline')\n  static ExtensionActionResult getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ExtensionActionResult>(create);\n  static ExtensionActionResult? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get extensionId => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set extensionId($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasExtensionId() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearExtensionId() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $1.ResponseCode get code => $_getN(1);\n  @$pb.TagNumber(2)\n  set code($1.ResponseCode v) { setField(2, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasCode() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearCode() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get message => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set message($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasMessage() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearMessage() => clearField(3);\n}\n\nclass ExtensionList extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ExtensionList', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extension'), createEmptyInstance: create)\n    ..pc<ExtensionMsg>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extensions', $pb.PbFieldType.PM, subBuilder: ExtensionMsg.create)\n    ..hasRequiredFields = false\n  ;\n\n  ExtensionList._() : super();\n  factory ExtensionList({\n    $core.Iterable<ExtensionMsg>? extensions,\n  }) {\n    final _result = create();\n    if (extensions != null) {\n      _result.extensions.addAll(extensions);\n    }\n    return _result;\n  }\n  factory ExtensionList.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ExtensionList.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ExtensionList clone() => ExtensionList()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ExtensionList copyWith(void Function(ExtensionList) updates) => super.copyWith((message) => updates(message as ExtensionList)) as ExtensionList; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ExtensionList create() => ExtensionList._();\n  ExtensionList createEmptyInstance() => create();\n  static $pb.PbList<ExtensionList> createRepeated() => $pb.PbList<ExtensionList>();\n  @$core.pragma('dart2js:noInline')\n  static ExtensionList getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ExtensionList>(create);\n  static ExtensionList? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.List<ExtensionMsg> get extensions => $_getList(0);\n}\n\nclass EditExtensionRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'EditExtensionRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extension'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extensionId')\n    ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enable')\n    ..hasRequiredFields = false\n  ;\n\n  EditExtensionRequest._() : super();\n  factory EditExtensionRequest({\n    $core.String? extensionId,\n    $core.bool? enable,\n  }) {\n    final _result = create();\n    if (extensionId != null) {\n      _result.extensionId = extensionId;\n    }\n    if (enable != null) {\n      _result.enable = enable;\n    }\n    return _result;\n  }\n  factory EditExtensionRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory EditExtensionRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  EditExtensionRequest clone() => EditExtensionRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  EditExtensionRequest copyWith(void Function(EditExtensionRequest) updates) => super.copyWith((message) => updates(message as EditExtensionRequest)) as EditExtensionRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static EditExtensionRequest create() => EditExtensionRequest._();\n  EditExtensionRequest createEmptyInstance() => create();\n  static $pb.PbList<EditExtensionRequest> createRepeated() => $pb.PbList<EditExtensionRequest>();\n  @$core.pragma('dart2js:noInline')\n  static EditExtensionRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EditExtensionRequest>(create);\n  static EditExtensionRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get extensionId => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set extensionId($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasExtensionId() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearExtensionId() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.bool get enable => $_getBF(1);\n  @$pb.TagNumber(2)\n  set enable($core.bool v) { $_setBool(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasEnable() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearEnable() => clearField(2);\n}\n\nclass ExtensionMsg extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ExtensionMsg', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extension'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'title')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'description')\n    ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enable')\n    ..hasRequiredFields = false\n  ;\n\n  ExtensionMsg._() : super();\n  factory ExtensionMsg({\n    $core.String? id,\n    $core.String? title,\n    $core.String? description,\n    $core.bool? enable,\n  }) {\n    final _result = create();\n    if (id != null) {\n      _result.id = id;\n    }\n    if (title != null) {\n      _result.title = title;\n    }\n    if (description != null) {\n      _result.description = description;\n    }\n    if (enable != null) {\n      _result.enable = enable;\n    }\n    return _result;\n  }\n  factory ExtensionMsg.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ExtensionMsg.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ExtensionMsg clone() => ExtensionMsg()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ExtensionMsg copyWith(void Function(ExtensionMsg) updates) => super.copyWith((message) => updates(message as ExtensionMsg)) as ExtensionMsg; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ExtensionMsg create() => ExtensionMsg._();\n  ExtensionMsg createEmptyInstance() => create();\n  static $pb.PbList<ExtensionMsg> createRepeated() => $pb.PbList<ExtensionMsg>();\n  @$core.pragma('dart2js:noInline')\n  static ExtensionMsg getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ExtensionMsg>(create);\n  static ExtensionMsg? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get id => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set id($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasId() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearId() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get title => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set title($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasTitle() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearTitle() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get description => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set description($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasDescription() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearDescription() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.bool get enable => $_getBF(3);\n  @$pb.TagNumber(4)\n  set enable($core.bool v) { $_setBool(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasEnable() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearEnable() => clearField(4);\n}\n\nclass ExtensionRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ExtensionRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extension'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extensionId')\n    ..m<$core.String, $core.String>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', entryClassName: 'ExtensionRequest.DataEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OS, packageName: const $pb.PackageName('extension'))\n    ..hasRequiredFields = false\n  ;\n\n  ExtensionRequest._() : super();\n  factory ExtensionRequest({\n    $core.String? extensionId,\n    $core.Map<$core.String, $core.String>? data,\n  }) {\n    final _result = create();\n    if (extensionId != null) {\n      _result.extensionId = extensionId;\n    }\n    if (data != null) {\n      _result.data.addAll(data);\n    }\n    return _result;\n  }\n  factory ExtensionRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ExtensionRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ExtensionRequest clone() => ExtensionRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ExtensionRequest copyWith(void Function(ExtensionRequest) updates) => super.copyWith((message) => updates(message as ExtensionRequest)) as ExtensionRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ExtensionRequest create() => ExtensionRequest._();\n  ExtensionRequest createEmptyInstance() => create();\n  static $pb.PbList<ExtensionRequest> createRepeated() => $pb.PbList<ExtensionRequest>();\n  @$core.pragma('dart2js:noInline')\n  static ExtensionRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ExtensionRequest>(create);\n  static ExtensionRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get extensionId => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set extensionId($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasExtensionId() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearExtensionId() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.Map<$core.String, $core.String> get data => $_getMap(1);\n}\n\nclass SendExtensionDataRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SendExtensionDataRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extension'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extensionId')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'button')\n    ..m<$core.String, $core.String>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', entryClassName: 'SendExtensionDataRequest.DataEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OS, packageName: const $pb.PackageName('extension'))\n    ..hasRequiredFields = false\n  ;\n\n  SendExtensionDataRequest._() : super();\n  factory SendExtensionDataRequest({\n    $core.String? extensionId,\n    $core.String? button,\n    $core.Map<$core.String, $core.String>? data,\n  }) {\n    final _result = create();\n    if (extensionId != null) {\n      _result.extensionId = extensionId;\n    }\n    if (button != null) {\n      _result.button = button;\n    }\n    if (data != null) {\n      _result.data.addAll(data);\n    }\n    return _result;\n  }\n  factory SendExtensionDataRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory SendExtensionDataRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  SendExtensionDataRequest clone() => SendExtensionDataRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  SendExtensionDataRequest copyWith(void Function(SendExtensionDataRequest) updates) => super.copyWith((message) => updates(message as SendExtensionDataRequest)) as SendExtensionDataRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static SendExtensionDataRequest create() => SendExtensionDataRequest._();\n  SendExtensionDataRequest createEmptyInstance() => create();\n  static $pb.PbList<SendExtensionDataRequest> createRepeated() => $pb.PbList<SendExtensionDataRequest>();\n  @$core.pragma('dart2js:noInline')\n  static SendExtensionDataRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SendExtensionDataRequest>(create);\n  static SendExtensionDataRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get extensionId => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set extensionId($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasExtensionId() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearExtensionId() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get button => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set button($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasButton() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearButton() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.Map<$core.String, $core.String> get data => $_getMap(2);\n}\n\nclass ExtensionResponse extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ExtensionResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extension'), createEmptyInstance: create)\n    ..e<ExtensionResponseType>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'type', $pb.PbFieldType.OE, defaultOrMaker: ExtensionResponseType.NOTHING, valueOf: ExtensionResponseType.valueOf, enumValues: ExtensionResponseType.values)\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extensionId')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'jsonUi')\n    ..hasRequiredFields = false\n  ;\n\n  ExtensionResponse._() : super();\n  factory ExtensionResponse({\n    ExtensionResponseType? type,\n    $core.String? extensionId,\n    $core.String? jsonUi,\n  }) {\n    final _result = create();\n    if (type != null) {\n      _result.type = type;\n    }\n    if (extensionId != null) {\n      _result.extensionId = extensionId;\n    }\n    if (jsonUi != null) {\n      _result.jsonUi = jsonUi;\n    }\n    return _result;\n  }\n  factory ExtensionResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ExtensionResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ExtensionResponse clone() => ExtensionResponse()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ExtensionResponse copyWith(void Function(ExtensionResponse) updates) => super.copyWith((message) => updates(message as ExtensionResponse)) as ExtensionResponse; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ExtensionResponse create() => ExtensionResponse._();\n  ExtensionResponse createEmptyInstance() => create();\n  static $pb.PbList<ExtensionResponse> createRepeated() => $pb.PbList<ExtensionResponse>();\n  @$core.pragma('dart2js:noInline')\n  static ExtensionResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ExtensionResponse>(create);\n  static ExtensionResponse? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  ExtensionResponseType get type => $_getN(0);\n  @$pb.TagNumber(1)\n  set type(ExtensionResponseType v) { setField(1, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasType() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearType() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get extensionId => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set extensionId($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasExtensionId() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearExtensionId() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get jsonUi => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set jsonUi($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasJsonUi() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearJsonUi() => clearField(3);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/extension/extension.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: extension/extension.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n// ignore_for_file: UNDEFINED_SHOWN_NAME\nimport 'dart:core' as $core;\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nclass ExtensionResponseType extends $pb.ProtobufEnum {\n  static const ExtensionResponseType NOTHING = ExtensionResponseType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NOTHING');\n  static const ExtensionResponseType UPDATE_UI = ExtensionResponseType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UPDATE_UI');\n  static const ExtensionResponseType SHOW_DIALOG = ExtensionResponseType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SHOW_DIALOG');\n  static const ExtensionResponseType END = ExtensionResponseType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'END');\n\n  static const $core.List<ExtensionResponseType> values = <ExtensionResponseType> [\n    NOTHING,\n    UPDATE_UI,\n    SHOW_DIALOG,\n    END,\n  ];\n\n  static final $core.Map<$core.int, ExtensionResponseType> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static ExtensionResponseType? valueOf($core.int value) => _byValue[value];\n\n  const ExtensionResponseType._($core.int v, $core.String n) : super(v, n);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/extension/extension.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: extension/extension.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n@$core.Deprecated('Use extensionResponseTypeDescriptor instead')\nconst ExtensionResponseType$json = const {\n  '1': 'ExtensionResponseType',\n  '2': const [\n    const {'1': 'NOTHING', '2': 0},\n    const {'1': 'UPDATE_UI', '2': 1},\n    const {'1': 'SHOW_DIALOG', '2': 2},\n    const {'1': 'END', '2': 3},\n  ],\n};\n\n/// Descriptor for `ExtensionResponseType`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List extensionResponseTypeDescriptor = $convert.base64Decode('ChVFeHRlbnNpb25SZXNwb25zZVR5cGUSCwoHTk9USElORxAAEg0KCVVQREFURV9VSRABEg8KC1NIT1dfRElBTE9HEAISBwoDRU5EEAM=');\n@$core.Deprecated('Use extensionActionResultDescriptor instead')\nconst ExtensionActionResult$json = const {\n  '1': 'ExtensionActionResult',\n  '2': const [\n    const {'1': 'extension_id', '3': 1, '4': 1, '5': 9, '10': 'extensionId'},\n    const {'1': 'code', '3': 2, '4': 1, '5': 14, '6': '.hcommon.ResponseCode', '10': 'code'},\n    const {'1': 'message', '3': 3, '4': 1, '5': 9, '10': 'message'},\n  ],\n};\n\n/// Descriptor for `ExtensionActionResult`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List extensionActionResultDescriptor = $convert.base64Decode('ChVFeHRlbnNpb25BY3Rpb25SZXN1bHQSIQoMZXh0ZW5zaW9uX2lkGAEgASgJUgtleHRlbnNpb25JZBIpCgRjb2RlGAIgASgOMhUuaGNvbW1vbi5SZXNwb25zZUNvZGVSBGNvZGUSGAoHbWVzc2FnZRgDIAEoCVIHbWVzc2FnZQ==');\n@$core.Deprecated('Use extensionListDescriptor instead')\nconst ExtensionList$json = const {\n  '1': 'ExtensionList',\n  '2': const [\n    const {'1': 'extensions', '3': 1, '4': 3, '5': 11, '6': '.extension.ExtensionMsg', '10': 'extensions'},\n  ],\n};\n\n/// Descriptor for `ExtensionList`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List extensionListDescriptor = $convert.base64Decode('Cg1FeHRlbnNpb25MaXN0EjcKCmV4dGVuc2lvbnMYASADKAsyFy5leHRlbnNpb24uRXh0ZW5zaW9uTXNnUgpleHRlbnNpb25z');\n@$core.Deprecated('Use editExtensionRequestDescriptor instead')\nconst EditExtensionRequest$json = const {\n  '1': 'EditExtensionRequest',\n  '2': const [\n    const {'1': 'extension_id', '3': 1, '4': 1, '5': 9, '10': 'extensionId'},\n    const {'1': 'enable', '3': 2, '4': 1, '5': 8, '10': 'enable'},\n  ],\n};\n\n/// Descriptor for `EditExtensionRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List editExtensionRequestDescriptor = $convert.base64Decode('ChRFZGl0RXh0ZW5zaW9uUmVxdWVzdBIhCgxleHRlbnNpb25faWQYASABKAlSC2V4dGVuc2lvbklkEhYKBmVuYWJsZRgCIAEoCFIGZW5hYmxl');\n@$core.Deprecated('Use extensionMsgDescriptor instead')\nconst ExtensionMsg$json = const {\n  '1': 'ExtensionMsg',\n  '2': const [\n    const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},\n    const {'1': 'title', '3': 2, '4': 1, '5': 9, '10': 'title'},\n    const {'1': 'description', '3': 3, '4': 1, '5': 9, '10': 'description'},\n    const {'1': 'enable', '3': 4, '4': 1, '5': 8, '10': 'enable'},\n  ],\n};\n\n/// Descriptor for `ExtensionMsg`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List extensionMsgDescriptor = $convert.base64Decode('CgxFeHRlbnNpb25Nc2cSDgoCaWQYASABKAlSAmlkEhQKBXRpdGxlGAIgASgJUgV0aXRsZRIgCgtkZXNjcmlwdGlvbhgDIAEoCVILZGVzY3JpcHRpb24SFgoGZW5hYmxlGAQgASgIUgZlbmFibGU=');\n@$core.Deprecated('Use extensionRequestDescriptor instead')\nconst ExtensionRequest$json = const {\n  '1': 'ExtensionRequest',\n  '2': const [\n    const {'1': 'extension_id', '3': 1, '4': 1, '5': 9, '10': 'extensionId'},\n    const {'1': 'data', '3': 2, '4': 3, '5': 11, '6': '.extension.ExtensionRequest.DataEntry', '10': 'data'},\n  ],\n  '3': const [ExtensionRequest_DataEntry$json],\n};\n\n@$core.Deprecated('Use extensionRequestDescriptor instead')\nconst ExtensionRequest_DataEntry$json = const {\n  '1': 'DataEntry',\n  '2': const [\n    const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},\n    const {'1': 'value', '3': 2, '4': 1, '5': 9, '10': 'value'},\n  ],\n  '7': const {'7': true},\n};\n\n/// Descriptor for `ExtensionRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List extensionRequestDescriptor = $convert.base64Decode('ChBFeHRlbnNpb25SZXF1ZXN0EiEKDGV4dGVuc2lvbl9pZBgBIAEoCVILZXh0ZW5zaW9uSWQSOQoEZGF0YRgCIAMoCzIlLmV4dGVuc2lvbi5FeHRlbnNpb25SZXF1ZXN0LkRhdGFFbnRyeVIEZGF0YRo3CglEYXRhRW50cnkSEAoDa2V5GAEgASgJUgNrZXkSFAoFdmFsdWUYAiABKAlSBXZhbHVlOgI4AQ==');\n@$core.Deprecated('Use sendExtensionDataRequestDescriptor instead')\nconst SendExtensionDataRequest$json = const {\n  '1': 'SendExtensionDataRequest',\n  '2': const [\n    const {'1': 'extension_id', '3': 1, '4': 1, '5': 9, '10': 'extensionId'},\n    const {'1': 'button', '3': 2, '4': 1, '5': 9, '10': 'button'},\n    const {'1': 'data', '3': 3, '4': 3, '5': 11, '6': '.extension.SendExtensionDataRequest.DataEntry', '10': 'data'},\n  ],\n  '3': const [SendExtensionDataRequest_DataEntry$json],\n};\n\n@$core.Deprecated('Use sendExtensionDataRequestDescriptor instead')\nconst SendExtensionDataRequest_DataEntry$json = const {\n  '1': 'DataEntry',\n  '2': const [\n    const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},\n    const {'1': 'value', '3': 2, '4': 1, '5': 9, '10': 'value'},\n  ],\n  '7': const {'7': true},\n};\n\n/// Descriptor for `SendExtensionDataRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List sendExtensionDataRequestDescriptor = $convert.base64Decode('ChhTZW5kRXh0ZW5zaW9uRGF0YVJlcXVlc3QSIQoMZXh0ZW5zaW9uX2lkGAEgASgJUgtleHRlbnNpb25JZBIWCgZidXR0b24YAiABKAlSBmJ1dHRvbhJBCgRkYXRhGAMgAygLMi0uZXh0ZW5zaW9uLlNlbmRFeHRlbnNpb25EYXRhUmVxdWVzdC5EYXRhRW50cnlSBGRhdGEaNwoJRGF0YUVudHJ5EhAKA2tleRgBIAEoCVIDa2V5EhQKBXZhbHVlGAIgASgJUgV2YWx1ZToCOAE=');\n@$core.Deprecated('Use extensionResponseDescriptor instead')\nconst ExtensionResponse$json = const {\n  '1': 'ExtensionResponse',\n  '2': const [\n    const {'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.extension.ExtensionResponseType', '10': 'type'},\n    const {'1': 'extension_id', '3': 2, '4': 1, '5': 9, '10': 'extensionId'},\n    const {'1': 'json_ui', '3': 3, '4': 1, '5': 9, '10': 'jsonUi'},\n  ],\n};\n\n/// Descriptor for `ExtensionResponse`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List extensionResponseDescriptor = $convert.base64Decode('ChFFeHRlbnNpb25SZXNwb25zZRI0CgR0eXBlGAEgASgOMiAuZXh0ZW5zaW9uLkV4dGVuc2lvblJlc3BvbnNlVHlwZVIEdHlwZRIhCgxleHRlbnNpb25faWQYAiABKAlSC2V4dGVuc2lvbklkEhcKB2pzb25fdWkYAyABKAlSBmpzb25VaQ==');\n"
  },
  {
    "path": "lib/hiddifycore/generated/extension/extension_service.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: extension/extension_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/extension/extension_service.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: extension/extension_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/extension/extension_service.pbgrpc.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: extension/extension_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:async' as $async;\n\nimport 'dart:core' as $core;\n\nimport 'package:grpc/service_api.dart' as $grpc;\nimport '../v2/hcommon/common.pb.dart' as $1;\nimport 'extension.pb.dart' as $6;\nexport 'extension_service.pb.dart';\n\nclass ExtensionHostServiceClient extends $grpc.Client {\n  static final _$listExtensions =\n      $grpc.ClientMethod<$1.Empty, $6.ExtensionList>(\n          '/extension.ExtensionHostService/ListExtensions',\n          ($1.Empty value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) => $6.ExtensionList.fromBuffer(value));\n  static final _$connect =\n      $grpc.ClientMethod<$6.ExtensionRequest, $6.ExtensionResponse>(\n          '/extension.ExtensionHostService/Connect',\n          ($6.ExtensionRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $6.ExtensionResponse.fromBuffer(value));\n  static final _$editExtension =\n      $grpc.ClientMethod<$6.EditExtensionRequest, $6.ExtensionActionResult>(\n          '/extension.ExtensionHostService/EditExtension',\n          ($6.EditExtensionRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $6.ExtensionActionResult.fromBuffer(value));\n  static final _$submitForm =\n      $grpc.ClientMethod<$6.SendExtensionDataRequest, $6.ExtensionActionResult>(\n          '/extension.ExtensionHostService/SubmitForm',\n          ($6.SendExtensionDataRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $6.ExtensionActionResult.fromBuffer(value));\n  static final _$close =\n      $grpc.ClientMethod<$6.ExtensionRequest, $6.ExtensionActionResult>(\n          '/extension.ExtensionHostService/Close',\n          ($6.ExtensionRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $6.ExtensionActionResult.fromBuffer(value));\n  static final _$getUI =\n      $grpc.ClientMethod<$6.ExtensionRequest, $6.ExtensionActionResult>(\n          '/extension.ExtensionHostService/GetUI',\n          ($6.ExtensionRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $6.ExtensionActionResult.fromBuffer(value));\n\n  ExtensionHostServiceClient($grpc.ClientChannel channel,\n      {$grpc.CallOptions? options,\n      $core.Iterable<$grpc.ClientInterceptor>? interceptors})\n      : super(channel, options: options, interceptors: interceptors);\n\n  $grpc.ResponseFuture<$6.ExtensionList> listExtensions($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$listExtensions, request, options: options);\n  }\n\n  $grpc.ResponseStream<$6.ExtensionResponse> connect(\n      $6.ExtensionRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createStreamingCall(\n        _$connect, $async.Stream.fromIterable([request]),\n        options: options);\n  }\n\n  $grpc.ResponseFuture<$6.ExtensionActionResult> editExtension(\n      $6.EditExtensionRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$editExtension, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$6.ExtensionActionResult> submitForm(\n      $6.SendExtensionDataRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$submitForm, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$6.ExtensionActionResult> close(\n      $6.ExtensionRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$close, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$6.ExtensionActionResult> getUI(\n      $6.ExtensionRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$getUI, request, options: options);\n  }\n}\n\nabstract class ExtensionHostServiceBase extends $grpc.Service {\n  $core.String get $name => 'extension.ExtensionHostService';\n\n  ExtensionHostServiceBase() {\n    $addMethod($grpc.ServiceMethod<$1.Empty, $6.ExtensionList>(\n        'ListExtensions',\n        listExtensions_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($6.ExtensionList value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$6.ExtensionRequest, $6.ExtensionResponse>(\n        'Connect',\n        connect_Pre,\n        false,\n        true,\n        ($core.List<$core.int> value) => $6.ExtensionRequest.fromBuffer(value),\n        ($6.ExtensionResponse value) => value.writeToBuffer()));\n    $addMethod(\n        $grpc.ServiceMethod<$6.EditExtensionRequest, $6.ExtensionActionResult>(\n            'EditExtension',\n            editExtension_Pre,\n            false,\n            false,\n            ($core.List<$core.int> value) =>\n                $6.EditExtensionRequest.fromBuffer(value),\n            ($6.ExtensionActionResult value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$6.SendExtensionDataRequest,\n            $6.ExtensionActionResult>(\n        'SubmitForm',\n        submitForm_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) =>\n            $6.SendExtensionDataRequest.fromBuffer(value),\n        ($6.ExtensionActionResult value) => value.writeToBuffer()));\n    $addMethod(\n        $grpc.ServiceMethod<$6.ExtensionRequest, $6.ExtensionActionResult>(\n            'Close',\n            close_Pre,\n            false,\n            false,\n            ($core.List<$core.int> value) =>\n                $6.ExtensionRequest.fromBuffer(value),\n            ($6.ExtensionActionResult value) => value.writeToBuffer()));\n    $addMethod(\n        $grpc.ServiceMethod<$6.ExtensionRequest, $6.ExtensionActionResult>(\n            'GetUI',\n            getUI_Pre,\n            false,\n            false,\n            ($core.List<$core.int> value) =>\n                $6.ExtensionRequest.fromBuffer(value),\n            ($6.ExtensionActionResult value) => value.writeToBuffer()));\n  }\n\n  $async.Future<$6.ExtensionList> listExtensions_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async {\n    return listExtensions(call, await request);\n  }\n\n  $async.Stream<$6.ExtensionResponse> connect_Pre($grpc.ServiceCall call,\n      $async.Future<$6.ExtensionRequest> request) async* {\n    yield* connect(call, await request);\n  }\n\n  $async.Future<$6.ExtensionActionResult> editExtension_Pre(\n      $grpc.ServiceCall call,\n      $async.Future<$6.EditExtensionRequest> request) async {\n    return editExtension(call, await request);\n  }\n\n  $async.Future<$6.ExtensionActionResult> submitForm_Pre($grpc.ServiceCall call,\n      $async.Future<$6.SendExtensionDataRequest> request) async {\n    return submitForm(call, await request);\n  }\n\n  $async.Future<$6.ExtensionActionResult> close_Pre($grpc.ServiceCall call,\n      $async.Future<$6.ExtensionRequest> request) async {\n    return close(call, await request);\n  }\n\n  $async.Future<$6.ExtensionActionResult> getUI_Pre($grpc.ServiceCall call,\n      $async.Future<$6.ExtensionRequest> request) async {\n    return getUI(call, await request);\n  }\n\n  $async.Future<$6.ExtensionList> listExtensions(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Stream<$6.ExtensionResponse> connect(\n      $grpc.ServiceCall call, $6.ExtensionRequest request);\n  $async.Future<$6.ExtensionActionResult> editExtension(\n      $grpc.ServiceCall call, $6.EditExtensionRequest request);\n  $async.Future<$6.ExtensionActionResult> submitForm(\n      $grpc.ServiceCall call, $6.SendExtensionDataRequest request);\n  $async.Future<$6.ExtensionActionResult> close(\n      $grpc.ServiceCall call, $6.ExtensionRequest request);\n  $async.Future<$6.ExtensionActionResult> getUI(\n      $grpc.ServiceCall call, $6.ExtensionRequest request);\n}\n"
  },
  {
    "path": "lib/hiddifycore/generated/extension/extension_service.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: extension/extension_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n"
  },
  {
    "path": "lib/hiddifycore/generated/google/protobuf/timestamp.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: google/protobuf/timestamp.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\nimport 'package:fixnum/fixnum.dart' as $fixnum;\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nimport 'package:protobuf/src/protobuf/mixins/well_known.dart' as $mixin;\n\nclass Timestamp extends $pb.GeneratedMessage with $mixin.TimestampMixin {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Timestamp', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'google.protobuf'), createEmptyInstance: create, toProto3Json: $mixin.TimestampMixin.toProto3JsonHelper, fromProto3Json: $mixin.TimestampMixin.fromProto3JsonHelper)\n    ..aInt64(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'seconds')\n    ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'nanos', $pb.PbFieldType.O3)\n    ..hasRequiredFields = false\n  ;\n\n  Timestamp._() : super();\n  factory Timestamp({\n    $fixnum.Int64? seconds,\n    $core.int? nanos,\n  }) {\n    final _result = create();\n    if (seconds != null) {\n      _result.seconds = seconds;\n    }\n    if (nanos != null) {\n      _result.nanos = nanos;\n    }\n    return _result;\n  }\n  factory Timestamp.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory Timestamp.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  Timestamp clone() => Timestamp()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  Timestamp copyWith(void Function(Timestamp) updates) => super.copyWith((message) => updates(message as Timestamp)) as Timestamp; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static Timestamp create() => Timestamp._();\n  Timestamp createEmptyInstance() => create();\n  static $pb.PbList<Timestamp> createRepeated() => $pb.PbList<Timestamp>();\n  @$core.pragma('dart2js:noInline')\n  static Timestamp getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Timestamp>(create);\n  static Timestamp? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $fixnum.Int64 get seconds => $_getI64(0);\n  @$pb.TagNumber(1)\n  set seconds($fixnum.Int64 v) { $_setInt64(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasSeconds() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearSeconds() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.int get nanos => $_getIZ(1);\n  @$pb.TagNumber(2)\n  set nanos($core.int v) { $_setSignedInt32(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasNanos() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearNanos() => clearField(2);\n  /// Creates a new instance from [dateTime].\n  ///\n  /// Time zone information will not be preserved.\n  static Timestamp fromDateTime($core.DateTime dateTime) {\n    final result = create();\n    $mixin.TimestampMixin.setFromDateTime(result, dateTime);\n    return result;\n  }\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/google/protobuf/timestamp.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: google/protobuf/timestamp.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/google/protobuf/timestamp.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: google/protobuf/timestamp.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n@$core.Deprecated('Use timestampDescriptor instead')\nconst Timestamp$json = const {\n  '1': 'Timestamp',\n  '2': const [\n    const {'1': 'seconds', '3': 1, '4': 1, '5': 3, '10': 'seconds'},\n    const {'1': 'nanos', '3': 2, '4': 1, '5': 5, '10': 'nanos'},\n  ],\n};\n\n/// Descriptor for `Timestamp`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List timestampDescriptor = $convert.base64Decode('CglUaW1lc3RhbXASGAoHc2Vjb25kcxgBIAEoA1IHc2Vjb25kcxIUCgVuYW5vcxgCIAEoBVIFbmFub3M=');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/common/common.pb.dart",
    "content": "//\n//  Generated code. Do not modify.\n//  source: v2/common/common.proto\n//\n// @dart = 2.12\n\n// ignore_for_file: annotate_overrides, camel_case_types, comment_references\n// ignore_for_file: constant_identifier_names, library_prefixes\n// ignore_for_file: non_constant_identifier_names, prefer_final_fields\n// ignore_for_file: unnecessary_import, unnecessary_this, unused_import\n\nimport 'dart:core' as $core;\n\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nimport 'common.pbenum.dart';\n\nexport 'common.pbenum.dart';\n\nclass Empty extends $pb.GeneratedMessage {\n  factory Empty() => create();\n  Empty._() : super();\n  factory Empty.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>\n      create()..mergeFromBuffer(i, r);\n  factory Empty.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>\n      create()..mergeFromJson(i, r);\n\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Empty',\n      package: const $pb.PackageName(_omitMessageNames ? '' : 'common'), createEmptyInstance: create)\n    ..hasRequiredFields = false;\n\n  @$core.Deprecated('Using this can add significant overhead to your binary. '\n      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n      'Will be removed in next major version')\n  Empty clone() => Empty()..mergeFromMessage(this);\n  @$core.Deprecated('Using this can add significant overhead to your binary. '\n      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n      'Will be removed in next major version')\n  Empty copyWith(void Function(Empty) updates) => super.copyWith((message) => updates(message as Empty)) as Empty;\n\n  $pb.BuilderInfo get info_ => _i;\n\n  @$core.pragma('dart2js:noInline')\n  static Empty create() => Empty._();\n  Empty createEmptyInstance() => create();\n  static $pb.PbList<Empty> createRepeated() => $pb.PbList<Empty>();\n  @$core.pragma('dart2js:noInline')\n  static Empty getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Empty>(create);\n  static Empty? _defaultInstance;\n}\n\nclass Response extends $pb.GeneratedMessage {\n  factory Response({\n    ResponseCode? code,\n    $core.String? message,\n  }) {\n    final $result = create();\n    if (code != null) {\n      $result.code = code;\n    }\n    if (message != null) {\n      $result.message = message;\n    }\n    return $result;\n  }\n  Response._() : super();\n  factory Response.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>\n      create()..mergeFromBuffer(i, r);\n  factory Response.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>\n      create()..mergeFromJson(i, r);\n\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Response',\n      package: const $pb.PackageName(_omitMessageNames ? '' : 'common'), createEmptyInstance: create)\n    ..e<ResponseCode>(1, _omitFieldNames ? '' : 'code', $pb.PbFieldType.OE,\n        defaultOrMaker: ResponseCode.OK, valueOf: ResponseCode.valueOf, enumValues: ResponseCode.values)\n    ..aOS(2, _omitFieldNames ? '' : 'message')\n    ..hasRequiredFields = false;\n\n  @$core.Deprecated('Using this can add significant overhead to your binary. '\n      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n      'Will be removed in next major version')\n  Response clone() => Response()..mergeFromMessage(this);\n  @$core.Deprecated('Using this can add significant overhead to your binary. '\n      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n      'Will be removed in next major version')\n  Response copyWith(void Function(Response) updates) =>\n      super.copyWith((message) => updates(message as Response)) as Response;\n\n  $pb.BuilderInfo get info_ => _i;\n\n  @$core.pragma('dart2js:noInline')\n  static Response create() => Response._();\n  Response createEmptyInstance() => create();\n  static $pb.PbList<Response> createRepeated() => $pb.PbList<Response>();\n  @$core.pragma('dart2js:noInline')\n  static Response getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Response>(create);\n  static Response? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  ResponseCode get code => $_getN(0);\n  @$pb.TagNumber(1)\n  set code(ResponseCode v) {\n    setField(1, v);\n  }\n\n  @$pb.TagNumber(1)\n  $core.bool hasCode() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearCode() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get message => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set message($core.String v) {\n    $_setString(1, v);\n  }\n\n  @$pb.TagNumber(2)\n  $core.bool hasMessage() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearMessage() => clearField(2);\n}\n\nconst _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');\nconst _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/common/common.pbenum.dart",
    "content": "//\n//  Generated code. Do not modify.\n//  source: v2/common/common.proto\n//\n// @dart = 2.12\n\n// ignore_for_file: annotate_overrides, camel_case_types, comment_references\n// ignore_for_file: constant_identifier_names, library_prefixes\n// ignore_for_file: non_constant_identifier_names, prefer_final_fields\n// ignore_for_file: unnecessary_import, unnecessary_this, unused_import\n\nimport 'dart:core' as $core;\n\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nclass ResponseCode extends $pb.ProtobufEnum {\n  static const ResponseCode OK = ResponseCode._(0, _omitEnumNames ? '' : 'OK');\n  static const ResponseCode FAILED = ResponseCode._(1, _omitEnumNames ? '' : 'FAILED');\n  static const ResponseCode AUTH_NEED = ResponseCode._(2, _omitEnumNames ? '' : 'AUTH_NEED');\n\n  static const $core.List<ResponseCode> values = <ResponseCode>[\n    OK,\n    FAILED,\n    AUTH_NEED,\n  ];\n\n  static final $core.Map<$core.int, ResponseCode> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static ResponseCode? valueOf($core.int value) => _byValue[value];\n\n  const ResponseCode._($core.int v, $core.String n) : super(v, n);\n}\n\nconst _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/common/common.pbjson.dart",
    "content": "//\n//  Generated code. Do not modify.\n//  source: v2/common/common.proto\n//\n// @dart = 2.12\n\n// ignore_for_file: annotate_overrides, camel_case_types, comment_references\n// ignore_for_file: constant_identifier_names, library_prefixes\n// ignore_for_file: non_constant_identifier_names, prefer_final_fields\n// ignore_for_file: unnecessary_import, unnecessary_this, unused_import\n\nimport 'dart:convert' as $convert;\nimport 'dart:core' as $core;\nimport 'dart:typed_data' as $typed_data;\n\n@$core.Deprecated('Use responseCodeDescriptor instead')\nconst ResponseCode$json = {\n  '1': 'ResponseCode',\n  '2': [\n    {'1': 'OK', '2': 0},\n    {'1': 'FAILED', '2': 1},\n    {'1': 'AUTH_NEED', '2': 2},\n  ],\n};\n\n/// Descriptor for `ResponseCode`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List responseCodeDescriptor =\n    $convert.base64Decode('CgxSZXNwb25zZUNvZGUSBgoCT0sQABIKCgZGQUlMRUQQARINCglBVVRIX05FRUQQAg==');\n\n@$core.Deprecated('Use emptyDescriptor instead')\nconst Empty$json = {\n  '1': 'Empty',\n};\n\n/// Descriptor for `Empty`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List emptyDescriptor = $convert.base64Decode('CgVFbXB0eQ==');\n\n@$core.Deprecated('Use responseDescriptor instead')\nconst Response$json = {\n  '1': 'Response',\n  '2': [\n    {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.common.ResponseCode', '10': 'code'},\n    {'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'},\n  ],\n};\n\n/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List responseDescriptor =\n    $convert.base64Decode('CghSZXNwb25zZRIoCgRjb2RlGAEgASgOMhQuY29tbW9uLlJlc3BvbnNlQ29kZVIEY29kZRIYCg'\n        'dtZXNzYWdlGAIgASgJUgdtZXNzYWdl');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/config/route_rule.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/config/route_rule.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nimport 'route_rule.pbenum.dart';\n\nexport 'route_rule.pbenum.dart';\n\nclass RouteRule extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RouteRule', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'config'), createEmptyInstance: create)\n    ..pc<Rule>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rules', $pb.PbFieldType.PM, subBuilder: Rule.create)\n    ..hasRequiredFields = false\n  ;\n\n  RouteRule._() : super();\n  factory RouteRule({\n    $core.Iterable<Rule>? rules,\n  }) {\n    final _result = create();\n    if (rules != null) {\n      _result.rules.addAll(rules);\n    }\n    return _result;\n  }\n  factory RouteRule.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory RouteRule.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  RouteRule clone() => RouteRule()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  RouteRule copyWith(void Function(RouteRule) updates) => super.copyWith((message) => updates(message as RouteRule)) as RouteRule; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static RouteRule create() => RouteRule._();\n  RouteRule createEmptyInstance() => create();\n  static $pb.PbList<RouteRule> createRepeated() => $pb.PbList<RouteRule>();\n  @$core.pragma('dart2js:noInline')\n  static RouteRule getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RouteRule>(create);\n  static RouteRule? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.List<Rule> get rules => $_getList(0);\n}\n\nclass Rule extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Rule', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'config'), createEmptyInstance: create)\n    ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'list_order', $pb.PbFieldType.OU3)\n    ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enabled')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')\n    ..e<Outbound>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'outbound', $pb.PbFieldType.OE, defaultOrMaker: Outbound.proxy, valueOf: Outbound.valueOf, enumValues: Outbound.values)\n    ..pPS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rule_set', protoName: 'rule_sets')\n    ..pPS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'package_name', protoName: 'package_names')\n    ..pPS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'process_name', protoName: 'process_names')\n    ..pPS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'process_path', protoName: 'process_paths')\n    ..e<Network>(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'network', $pb.PbFieldType.OE, defaultOrMaker: Network.all, valueOf: Network.valueOf, enumValues: Network.values)\n    ..pPS(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'port_range', protoName: 'port_ranges')\n    ..pPS(11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'source_port_range', protoName: 'source_port_ranges')\n    ..pc<Protocol>(12, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'protocol', $pb.PbFieldType.KE, protoName: 'protocols', valueOf: Protocol.valueOf, enumValues: Protocol.values, defaultEnumValue: Protocol.tls)\n    ..pPS(13, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ip_cidr', protoName: 'ip_cidrs')\n    ..pPS(14, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'source_ip_cidr', protoName: 'source_ip_cidrs')\n    ..pPS(15, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'domain', protoName: 'domains')\n    ..pPS(16, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'domain_suffix', protoName: 'domain_suffixes')\n    ..pPS(17, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'domain_keyword', protoName: 'domain_keywords')\n    ..pPS(18, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'domain_regex', protoName: 'domain_regexes')\n    ..hasRequiredFields = false\n  ;\n\n  Rule._() : super();\n  factory Rule({\n    $core.int? listOrder,\n    $core.bool? enabled,\n    $core.String? name,\n    Outbound? outbound,\n    $core.Iterable<$core.String>? ruleSets,\n    $core.Iterable<$core.String>? packageNames,\n    $core.Iterable<$core.String>? processNames,\n    $core.Iterable<$core.String>? processPaths,\n    Network? network,\n    $core.Iterable<$core.String>? portRanges,\n    $core.Iterable<$core.String>? sourcePortRanges,\n    $core.Iterable<Protocol>? protocols,\n    $core.Iterable<$core.String>? ipCidrs,\n    $core.Iterable<$core.String>? sourceIpCidrs,\n    $core.Iterable<$core.String>? domains,\n    $core.Iterable<$core.String>? domainSuffixes,\n    $core.Iterable<$core.String>? domainKeywords,\n    $core.Iterable<$core.String>? domainRegexes,\n  }) {\n    final _result = create();\n    if (listOrder != null) {\n      _result.listOrder = listOrder;\n    }\n    if (enabled != null) {\n      _result.enabled = enabled;\n    }\n    if (name != null) {\n      _result.name = name;\n    }\n    if (outbound != null) {\n      _result.outbound = outbound;\n    }\n    if (ruleSets != null) {\n      _result.ruleSets.addAll(ruleSets);\n    }\n    if (packageNames != null) {\n      _result.packageNames.addAll(packageNames);\n    }\n    if (processNames != null) {\n      _result.processNames.addAll(processNames);\n    }\n    if (processPaths != null) {\n      _result.processPaths.addAll(processPaths);\n    }\n    if (network != null) {\n      _result.network = network;\n    }\n    if (portRanges != null) {\n      _result.portRanges.addAll(portRanges);\n    }\n    if (sourcePortRanges != null) {\n      _result.sourcePortRanges.addAll(sourcePortRanges);\n    }\n    if (protocols != null) {\n      _result.protocols.addAll(protocols);\n    }\n    if (ipCidrs != null) {\n      _result.ipCidrs.addAll(ipCidrs);\n    }\n    if (sourceIpCidrs != null) {\n      _result.sourceIpCidrs.addAll(sourceIpCidrs);\n    }\n    if (domains != null) {\n      _result.domains.addAll(domains);\n    }\n    if (domainSuffixes != null) {\n      _result.domainSuffixes.addAll(domainSuffixes);\n    }\n    if (domainKeywords != null) {\n      _result.domainKeywords.addAll(domainKeywords);\n    }\n    if (domainRegexes != null) {\n      _result.domainRegexes.addAll(domainRegexes);\n    }\n    return _result;\n  }\n  factory Rule.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory Rule.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  Rule clone() => Rule()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  Rule copyWith(void Function(Rule) updates) => super.copyWith((message) => updates(message as Rule)) as Rule; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static Rule create() => Rule._();\n  Rule createEmptyInstance() => create();\n  static $pb.PbList<Rule> createRepeated() => $pb.PbList<Rule>();\n  @$core.pragma('dart2js:noInline')\n  static Rule getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Rule>(create);\n  static Rule? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.int get listOrder => $_getIZ(0);\n  @$pb.TagNumber(1)\n  set listOrder($core.int v) { $_setUnsignedInt32(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasListOrder() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearListOrder() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.bool get enabled => $_getBF(1);\n  @$pb.TagNumber(2)\n  set enabled($core.bool v) { $_setBool(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasEnabled() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearEnabled() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get name => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set name($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasName() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearName() => clearField(3);\n\n  @$pb.TagNumber(4)\n  Outbound get outbound => $_getN(3);\n  @$pb.TagNumber(4)\n  set outbound(Outbound v) { setField(4, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasOutbound() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearOutbound() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.List<$core.String> get ruleSets => $_getList(4);\n\n  @$pb.TagNumber(6)\n  $core.List<$core.String> get packageNames => $_getList(5);\n\n  @$pb.TagNumber(7)\n  $core.List<$core.String> get processNames => $_getList(6);\n\n  @$pb.TagNumber(8)\n  $core.List<$core.String> get processPaths => $_getList(7);\n\n  @$pb.TagNumber(9)\n  Network get network => $_getN(8);\n  @$pb.TagNumber(9)\n  set network(Network v) { setField(9, v); }\n  @$pb.TagNumber(9)\n  $core.bool hasNetwork() => $_has(8);\n  @$pb.TagNumber(9)\n  void clearNetwork() => clearField(9);\n\n  @$pb.TagNumber(10)\n  $core.List<$core.String> get portRanges => $_getList(9);\n\n  @$pb.TagNumber(11)\n  $core.List<$core.String> get sourcePortRanges => $_getList(10);\n\n  @$pb.TagNumber(12)\n  $core.List<Protocol> get protocols => $_getList(11);\n\n  @$pb.TagNumber(13)\n  $core.List<$core.String> get ipCidrs => $_getList(12);\n\n  @$pb.TagNumber(14)\n  $core.List<$core.String> get sourceIpCidrs => $_getList(13);\n\n  @$pb.TagNumber(15)\n  $core.List<$core.String> get domains => $_getList(14);\n\n  @$pb.TagNumber(16)\n  $core.List<$core.String> get domainSuffixes => $_getList(15);\n\n  @$pb.TagNumber(17)\n  $core.List<$core.String> get domainKeywords => $_getList(16);\n\n  @$pb.TagNumber(18)\n  $core.List<$core.String> get domainRegexes => $_getList(17);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/config/route_rule.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/config/route_rule.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n// ignore_for_file: UNDEFINED_SHOWN_NAME\nimport 'dart:core' as $core;\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nclass Outbound extends $pb.ProtobufEnum {\n  static const Outbound proxy = Outbound._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'proxy');\n  static const Outbound direct = Outbound._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'direct');\n  static const Outbound direct_with_fragment = Outbound._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'direct_with_fragment');\n  static const Outbound block = Outbound._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'block');\n\n  static const $core.List<Outbound> values = <Outbound> [\n    proxy,\n    direct,\n    direct_with_fragment,\n    block,\n  ];\n\n  static final $core.Map<$core.int, Outbound> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static Outbound? valueOf($core.int value) => _byValue[value];\n\n  const Outbound._($core.int v, $core.String n) : super(v, n);\n}\n\nclass Network extends $pb.ProtobufEnum {\n  static const Network all = Network._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'all');\n  static const Network tcp = Network._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'tcp');\n  static const Network udp = Network._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'udp');\n\n  static const $core.List<Network> values = <Network> [\n    all,\n    tcp,\n    udp,\n  ];\n\n  static final $core.Map<$core.int, Network> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static Network? valueOf($core.int value) => _byValue[value];\n\n  const Network._($core.int v, $core.String n) : super(v, n);\n}\n\nclass Protocol extends $pb.ProtobufEnum {\n  static const Protocol tls = Protocol._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'tls');\n  static const Protocol http = Protocol._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'http');\n  static const Protocol quic = Protocol._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'quic');\n  static const Protocol stun = Protocol._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'stun');\n  static const Protocol dns = Protocol._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'dns');\n  static const Protocol bittorrent = Protocol._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'bittorrent');\n\n  static const $core.List<Protocol> values = <Protocol> [\n    tls,\n    http,\n    quic,\n    stun,\n    dns,\n    bittorrent,\n  ];\n\n  static final $core.Map<$core.int, Protocol> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static Protocol? valueOf($core.int value) => _byValue[value];\n\n  const Protocol._($core.int v, $core.String n) : super(v, n);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/config/route_rule.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/config/route_rule.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n@$core.Deprecated('Use outboundDescriptor instead')\nconst Outbound$json = const {\n  '1': 'Outbound',\n  '2': const [\n    const {'1': 'proxy', '2': 0},\n    const {'1': 'direct', '2': 1},\n    const {'1': 'direct_with_fragment', '2': 2},\n    const {'1': 'block', '2': 3},\n  ],\n};\n\n/// Descriptor for `Outbound`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List outboundDescriptor = $convert.base64Decode('CghPdXRib3VuZBIJCgVwcm94eRAAEgoKBmRpcmVjdBABEhgKFGRpcmVjdF93aXRoX2ZyYWdtZW50EAISCQoFYmxvY2sQAw==');\n@$core.Deprecated('Use networkDescriptor instead')\nconst Network$json = const {\n  '1': 'Network',\n  '2': const [\n    const {'1': 'all', '2': 0},\n    const {'1': 'tcp', '2': 1},\n    const {'1': 'udp', '2': 2},\n  ],\n};\n\n/// Descriptor for `Network`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List networkDescriptor = $convert.base64Decode('CgdOZXR3b3JrEgcKA2FsbBAAEgcKA3RjcBABEgcKA3VkcBAC');\n@$core.Deprecated('Use protocolDescriptor instead')\nconst Protocol$json = const {\n  '1': 'Protocol',\n  '2': const [\n    const {'1': 'tls', '2': 0},\n    const {'1': 'http', '2': 1},\n    const {'1': 'quic', '2': 2},\n    const {'1': 'stun', '2': 3},\n    const {'1': 'dns', '2': 4},\n    const {'1': 'bittorrent', '2': 5},\n  ],\n};\n\n/// Descriptor for `Protocol`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List protocolDescriptor = $convert.base64Decode('CghQcm90b2NvbBIHCgN0bHMQABIICgRodHRwEAESCAoEcXVpYxACEggKBHN0dW4QAxIHCgNkbnMQBBIOCgpiaXR0b3JyZW50EAU=');\n@$core.Deprecated('Use routeRuleDescriptor instead')\nconst RouteRule$json = const {\n  '1': 'RouteRule',\n  '2': const [\n    const {'1': 'rules', '3': 1, '4': 3, '5': 11, '6': '.config.Rule', '10': 'rules'},\n  ],\n};\n\n/// Descriptor for `RouteRule`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List routeRuleDescriptor = $convert.base64Decode('CglSb3V0ZVJ1bGUSIgoFcnVsZXMYASADKAsyDC5jb25maWcuUnVsZVIFcnVsZXM=');\n@$core.Deprecated('Use ruleDescriptor instead')\nconst Rule$json = const {\n  '1': 'Rule',\n  '2': const [\n    const {'1': 'list_order', '3': 1, '4': 1, '5': 13, '10': 'list_order'},\n    const {'1': 'enabled', '3': 2, '4': 1, '5': 8, '10': 'enabled'},\n    const {'1': 'name', '3': 3, '4': 1, '5': 9, '10': 'name'},\n    const {'1': 'outbound', '3': 4, '4': 1, '5': 14, '6': '.config.Outbound', '10': 'outbound'},\n    const {'1': 'rule_sets', '3': 5, '4': 3, '5': 9, '10': 'rule_set'},\n    const {'1': 'package_names', '3': 6, '4': 3, '5': 9, '10': 'package_name'},\n    const {'1': 'process_names', '3': 7, '4': 3, '5': 9, '10': 'process_name'},\n    const {'1': 'process_paths', '3': 8, '4': 3, '5': 9, '10': 'process_path'},\n    const {'1': 'network', '3': 9, '4': 1, '5': 14, '6': '.config.Network', '10': 'network'},\n    const {'1': 'port_ranges', '3': 10, '4': 3, '5': 9, '10': 'port_range'},\n    const {'1': 'source_port_ranges', '3': 11, '4': 3, '5': 9, '10': 'source_port_range'},\n    const {'1': 'protocols', '3': 12, '4': 3, '5': 14, '6': '.config.Protocol', '10': 'protocol'},\n    const {'1': 'ip_cidrs', '3': 13, '4': 3, '5': 9, '10': 'ip_cidr'},\n    const {'1': 'source_ip_cidrs', '3': 14, '4': 3, '5': 9, '10': 'source_ip_cidr'},\n    const {'1': 'domains', '3': 15, '4': 3, '5': 9, '10': 'domain'},\n    const {'1': 'domain_suffixes', '3': 16, '4': 3, '5': 9, '10': 'domain_suffix'},\n    const {'1': 'domain_keywords', '3': 17, '4': 3, '5': 9, '10': 'domain_keyword'},\n    const {'1': 'domain_regexes', '3': 18, '4': 3, '5': 9, '10': 'domain_regex'},\n  ],\n};\n\n/// Descriptor for `Rule`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List ruleDescriptor = $convert.base64Decode('CgRSdWxlEh4KCmxpc3Rfb3JkZXIYASABKA1SCmxpc3Rfb3JkZXISGAoHZW5hYmxlZBgCIAEoCFIHZW5hYmxlZBISCgRuYW1lGAMgASgJUgRuYW1lEiwKCG91dGJvdW5kGAQgASgOMhAuY29uZmlnLk91dGJvdW5kUghvdXRib3VuZBIbCglydWxlX3NldHMYBSADKAlSCHJ1bGVfc2V0EiMKDXBhY2thZ2VfbmFtZXMYBiADKAlSDHBhY2thZ2VfbmFtZRIjCg1wcm9jZXNzX25hbWVzGAcgAygJUgxwcm9jZXNzX25hbWUSIwoNcHJvY2Vzc19wYXRocxgIIAMoCVIMcHJvY2Vzc19wYXRoEikKB25ldHdvcmsYCSABKA4yDy5jb25maWcuTmV0d29ya1IHbmV0d29yaxIfCgtwb3J0X3JhbmdlcxgKIAMoCVIKcG9ydF9yYW5nZRItChJzb3VyY2VfcG9ydF9yYW5nZXMYCyADKAlSEXNvdXJjZV9wb3J0X3JhbmdlEi0KCXByb3RvY29scxgMIAMoDjIQLmNvbmZpZy5Qcm90b2NvbFIIcHJvdG9jb2wSGQoIaXBfY2lkcnMYDSADKAlSB2lwX2NpZHISJwoPc291cmNlX2lwX2NpZHJzGA4gAygJUg5zb3VyY2VfaXBfY2lkchIXCgdkb21haW5zGA8gAygJUgZkb21haW4SJgoPZG9tYWluX3N1ZmZpeGVzGBAgAygJUg1kb21haW5fc3VmZml4EicKD2RvbWFpbl9rZXl3b3JkcxgRIAMoCVIOZG9tYWluX2tleXdvcmQSJAoOZG9tYWluX3JlZ2V4ZXMYEiADKAlSDGRvbWFpbl9yZWdleA==');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcommon/common.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcommon/common.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nimport 'common.pbenum.dart';\n\nexport 'common.pbenum.dart';\n\nclass Empty extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Empty', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcommon'), createEmptyInstance: create)\n    ..hasRequiredFields = false\n  ;\n\n  Empty._() : super();\n  factory Empty() => create();\n  factory Empty.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory Empty.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  Empty clone() => Empty()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  Empty copyWith(void Function(Empty) updates) => super.copyWith((message) => updates(message as Empty)) as Empty; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static Empty create() => Empty._();\n  Empty createEmptyInstance() => create();\n  static $pb.PbList<Empty> createRepeated() => $pb.PbList<Empty>();\n  @$core.pragma('dart2js:noInline')\n  static Empty getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Empty>(create);\n  static Empty? _defaultInstance;\n}\n\nclass Response extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Response', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcommon'), createEmptyInstance: create)\n    ..e<ResponseCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: ResponseCode.OK, valueOf: ResponseCode.valueOf, enumValues: ResponseCode.values)\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message')\n    ..hasRequiredFields = false\n  ;\n\n  Response._() : super();\n  factory Response({\n    ResponseCode? code,\n    $core.String? message,\n  }) {\n    final _result = create();\n    if (code != null) {\n      _result.code = code;\n    }\n    if (message != null) {\n      _result.message = message;\n    }\n    return _result;\n  }\n  factory Response.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory Response.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  Response clone() => Response()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  Response copyWith(void Function(Response) updates) => super.copyWith((message) => updates(message as Response)) as Response; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static Response create() => Response._();\n  Response createEmptyInstance() => create();\n  static $pb.PbList<Response> createRepeated() => $pb.PbList<Response>();\n  @$core.pragma('dart2js:noInline')\n  static Response getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Response>(create);\n  static Response? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  ResponseCode get code => $_getN(0);\n  @$pb.TagNumber(1)\n  set code(ResponseCode v) { setField(1, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasCode() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearCode() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get message => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set message($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasMessage() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearMessage() => clearField(2);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcommon/common.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcommon/common.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n// ignore_for_file: UNDEFINED_SHOWN_NAME\nimport 'dart:core' as $core;\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nclass ResponseCode extends $pb.ProtobufEnum {\n  static const ResponseCode OK = ResponseCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'OK');\n  static const ResponseCode FAILED = ResponseCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FAILED');\n  static const ResponseCode AUTH_NEED = ResponseCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AUTH_NEED');\n\n  static const $core.List<ResponseCode> values = <ResponseCode> [\n    OK,\n    FAILED,\n    AUTH_NEED,\n  ];\n\n  static final $core.Map<$core.int, ResponseCode> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static ResponseCode? valueOf($core.int value) => _byValue[value];\n\n  const ResponseCode._($core.int v, $core.String n) : super(v, n);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcommon/common.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcommon/common.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n@$core.Deprecated('Use responseCodeDescriptor instead')\nconst ResponseCode$json = const {\n  '1': 'ResponseCode',\n  '2': const [\n    const {'1': 'OK', '2': 0},\n    const {'1': 'FAILED', '2': 1},\n    const {'1': 'AUTH_NEED', '2': 2},\n  ],\n};\n\n/// Descriptor for `ResponseCode`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List responseCodeDescriptor = $convert.base64Decode('CgxSZXNwb25zZUNvZGUSBgoCT0sQABIKCgZGQUlMRUQQARINCglBVVRIX05FRUQQAg==');\n@$core.Deprecated('Use emptyDescriptor instead')\nconst Empty$json = const {\n  '1': 'Empty',\n};\n\n/// Descriptor for `Empty`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List emptyDescriptor = $convert.base64Decode('CgVFbXB0eQ==');\n@$core.Deprecated('Use responseDescriptor instead')\nconst Response$json = const {\n  '1': 'Response',\n  '2': const [\n    const {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.hcommon.ResponseCode', '10': 'code'},\n    const {'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'},\n  ],\n};\n\n/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List responseDescriptor = $convert.base64Decode('CghSZXNwb25zZRIpCgRjb2RlGAEgASgOMhUuaGNvbW1vbi5SZXNwb25zZUNvZGVSBGNvZGUSGAoHbWVzc2FnZRgCIAEoCVIHbWVzc2FnZQ==');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/hcore.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/hcore.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\nimport 'package:fixnum/fixnum.dart' as $fixnum;\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nimport '../../google/protobuf/timestamp.pb.dart' as $7;\n\nimport 'hcore.pbenum.dart';\nimport '../hcommon/common.pbenum.dart' as $1;\n\nexport 'hcore.pbenum.dart';\n\nclass CoreInfoResponse extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CoreInfoResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..e<CoreStates>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'coreState', $pb.PbFieldType.OE, defaultOrMaker: CoreStates.STOPPED, valueOf: CoreStates.valueOf, enumValues: CoreStates.values)\n    ..e<MessageType>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'messageType', $pb.PbFieldType.OE, defaultOrMaker: MessageType.EMPTY, valueOf: MessageType.valueOf, enumValues: MessageType.values)\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message')\n    ..hasRequiredFields = false\n  ;\n\n  CoreInfoResponse._() : super();\n  factory CoreInfoResponse({\n    CoreStates? coreState,\n    MessageType? messageType,\n    $core.String? message,\n  }) {\n    final _result = create();\n    if (coreState != null) {\n      _result.coreState = coreState;\n    }\n    if (messageType != null) {\n      _result.messageType = messageType;\n    }\n    if (message != null) {\n      _result.message = message;\n    }\n    return _result;\n  }\n  factory CoreInfoResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory CoreInfoResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  CoreInfoResponse clone() => CoreInfoResponse()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  CoreInfoResponse copyWith(void Function(CoreInfoResponse) updates) => super.copyWith((message) => updates(message as CoreInfoResponse)) as CoreInfoResponse; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static CoreInfoResponse create() => CoreInfoResponse._();\n  CoreInfoResponse createEmptyInstance() => create();\n  static $pb.PbList<CoreInfoResponse> createRepeated() => $pb.PbList<CoreInfoResponse>();\n  @$core.pragma('dart2js:noInline')\n  static CoreInfoResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CoreInfoResponse>(create);\n  static CoreInfoResponse? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  CoreStates get coreState => $_getN(0);\n  @$pb.TagNumber(1)\n  set coreState(CoreStates v) { setField(1, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasCoreState() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearCoreState() => clearField(1);\n\n  @$pb.TagNumber(2)\n  MessageType get messageType => $_getN(1);\n  @$pb.TagNumber(2)\n  set messageType(MessageType v) { setField(2, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasMessageType() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearMessageType() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get message => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set message($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasMessage() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearMessage() => clearField(3);\n}\n\nclass StartRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'StartRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'configPath')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'configContent')\n    ..aOB(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableMemoryLimit')\n    ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'delayStart')\n    ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enableOldCommandServer')\n    ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enableRawConfig')\n    ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'configName')\n    ..hasRequiredFields = false\n  ;\n\n  StartRequest._() : super();\n  factory StartRequest({\n    $core.String? configPath,\n    $core.String? configContent,\n    $core.bool? disableMemoryLimit,\n    $core.bool? delayStart,\n    $core.bool? enableOldCommandServer,\n    $core.bool? enableRawConfig,\n    $core.String? configName,\n  }) {\n    final _result = create();\n    if (configPath != null) {\n      _result.configPath = configPath;\n    }\n    if (configContent != null) {\n      _result.configContent = configContent;\n    }\n    if (disableMemoryLimit != null) {\n      _result.disableMemoryLimit = disableMemoryLimit;\n    }\n    if (delayStart != null) {\n      _result.delayStart = delayStart;\n    }\n    if (enableOldCommandServer != null) {\n      _result.enableOldCommandServer = enableOldCommandServer;\n    }\n    if (enableRawConfig != null) {\n      _result.enableRawConfig = enableRawConfig;\n    }\n    if (configName != null) {\n      _result.configName = configName;\n    }\n    return _result;\n  }\n  factory StartRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory StartRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  StartRequest clone() => StartRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  StartRequest copyWith(void Function(StartRequest) updates) => super.copyWith((message) => updates(message as StartRequest)) as StartRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static StartRequest create() => StartRequest._();\n  StartRequest createEmptyInstance() => create();\n  static $pb.PbList<StartRequest> createRepeated() => $pb.PbList<StartRequest>();\n  @$core.pragma('dart2js:noInline')\n  static StartRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<StartRequest>(create);\n  static StartRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get configPath => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set configPath($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasConfigPath() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearConfigPath() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get configContent => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set configContent($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasConfigContent() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearConfigContent() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.bool get disableMemoryLimit => $_getBF(2);\n  @$pb.TagNumber(3)\n  set disableMemoryLimit($core.bool v) { $_setBool(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasDisableMemoryLimit() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearDisableMemoryLimit() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.bool get delayStart => $_getBF(3);\n  @$pb.TagNumber(4)\n  set delayStart($core.bool v) { $_setBool(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasDelayStart() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearDelayStart() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.bool get enableOldCommandServer => $_getBF(4);\n  @$pb.TagNumber(5)\n  set enableOldCommandServer($core.bool v) { $_setBool(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasEnableOldCommandServer() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearEnableOldCommandServer() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $core.bool get enableRawConfig => $_getBF(5);\n  @$pb.TagNumber(6)\n  set enableRawConfig($core.bool v) { $_setBool(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasEnableRawConfig() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearEnableRawConfig() => clearField(6);\n\n  @$pb.TagNumber(7)\n  $core.String get configName => $_getSZ(6);\n  @$pb.TagNumber(7)\n  set configName($core.String v) { $_setString(6, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasConfigName() => $_has(6);\n  @$pb.TagNumber(7)\n  void clearConfigName() => clearField(7);\n}\n\nclass CloseRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CloseRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..e<SetupMode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mode', $pb.PbFieldType.OE, defaultOrMaker: SetupMode.OLD, valueOf: SetupMode.valueOf, enumValues: SetupMode.values)\n    ..hasRequiredFields = false\n  ;\n\n  CloseRequest._() : super();\n  factory CloseRequest({\n    SetupMode? mode,\n  }) {\n    final _result = create();\n    if (mode != null) {\n      _result.mode = mode;\n    }\n    return _result;\n  }\n  factory CloseRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory CloseRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  CloseRequest clone() => CloseRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  CloseRequest copyWith(void Function(CloseRequest) updates) => super.copyWith((message) => updates(message as CloseRequest)) as CloseRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static CloseRequest create() => CloseRequest._();\n  CloseRequest createEmptyInstance() => create();\n  static $pb.PbList<CloseRequest> createRepeated() => $pb.PbList<CloseRequest>();\n  @$core.pragma('dart2js:noInline')\n  static CloseRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CloseRequest>(create);\n  static CloseRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  SetupMode get mode => $_getN(0);\n  @$pb.TagNumber(1)\n  set mode(SetupMode v) { setField(1, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasMode() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearMode() => clearField(1);\n}\n\nclass SetupRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SetupRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'basePath')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'workingDir')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'tempDir')\n    ..aInt64(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'flutterStatusPort')\n    ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'listen')\n    ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'secret')\n    ..aOB(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'debug')\n    ..e<SetupMode>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mode', $pb.PbFieldType.OE, defaultOrMaker: SetupMode.OLD, valueOf: SetupMode.valueOf, enumValues: SetupMode.values)\n    ..aOB(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fixAndroidStack')\n    ..hasRequiredFields = false\n  ;\n\n  SetupRequest._() : super();\n  factory SetupRequest({\n    $core.String? basePath,\n    $core.String? workingDir,\n    $core.String? tempDir,\n    $fixnum.Int64? flutterStatusPort,\n    $core.String? listen,\n    $core.String? secret,\n    $core.bool? debug,\n    SetupMode? mode,\n    $core.bool? fixAndroidStack,\n  }) {\n    final _result = create();\n    if (basePath != null) {\n      _result.basePath = basePath;\n    }\n    if (workingDir != null) {\n      _result.workingDir = workingDir;\n    }\n    if (tempDir != null) {\n      _result.tempDir = tempDir;\n    }\n    if (flutterStatusPort != null) {\n      _result.flutterStatusPort = flutterStatusPort;\n    }\n    if (listen != null) {\n      _result.listen = listen;\n    }\n    if (secret != null) {\n      _result.secret = secret;\n    }\n    if (debug != null) {\n      _result.debug = debug;\n    }\n    if (mode != null) {\n      _result.mode = mode;\n    }\n    if (fixAndroidStack != null) {\n      _result.fixAndroidStack = fixAndroidStack;\n    }\n    return _result;\n  }\n  factory SetupRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory SetupRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  SetupRequest clone() => SetupRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  SetupRequest copyWith(void Function(SetupRequest) updates) => super.copyWith((message) => updates(message as SetupRequest)) as SetupRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static SetupRequest create() => SetupRequest._();\n  SetupRequest createEmptyInstance() => create();\n  static $pb.PbList<SetupRequest> createRepeated() => $pb.PbList<SetupRequest>();\n  @$core.pragma('dart2js:noInline')\n  static SetupRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SetupRequest>(create);\n  static SetupRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get basePath => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set basePath($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasBasePath() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearBasePath() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get workingDir => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set workingDir($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasWorkingDir() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearWorkingDir() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get tempDir => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set tempDir($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasTempDir() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearTempDir() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $fixnum.Int64 get flutterStatusPort => $_getI64(3);\n  @$pb.TagNumber(4)\n  set flutterStatusPort($fixnum.Int64 v) { $_setInt64(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasFlutterStatusPort() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearFlutterStatusPort() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.String get listen => $_getSZ(4);\n  @$pb.TagNumber(5)\n  set listen($core.String v) { $_setString(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasListen() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearListen() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $core.String get secret => $_getSZ(5);\n  @$pb.TagNumber(6)\n  set secret($core.String v) { $_setString(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasSecret() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearSecret() => clearField(6);\n\n  @$pb.TagNumber(7)\n  $core.bool get debug => $_getBF(6);\n  @$pb.TagNumber(7)\n  set debug($core.bool v) { $_setBool(6, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasDebug() => $_has(6);\n  @$pb.TagNumber(7)\n  void clearDebug() => clearField(7);\n\n  @$pb.TagNumber(8)\n  SetupMode get mode => $_getN(7);\n  @$pb.TagNumber(8)\n  set mode(SetupMode v) { setField(8, v); }\n  @$pb.TagNumber(8)\n  $core.bool hasMode() => $_has(7);\n  @$pb.TagNumber(8)\n  void clearMode() => clearField(8);\n\n  @$pb.TagNumber(9)\n  $core.bool get fixAndroidStack => $_getBF(8);\n  @$pb.TagNumber(9)\n  set fixAndroidStack($core.bool v) { $_setBool(8, v); }\n  @$pb.TagNumber(9)\n  $core.bool hasFixAndroidStack() => $_has(8);\n  @$pb.TagNumber(9)\n  void clearFixAndroidStack() => clearField(9);\n}\n\nclass SystemInfo extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SystemInfo', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aInt64(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'memory')\n    ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'goroutines', $pb.PbFieldType.O3)\n    ..a<$core.int>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'connectionsIn', $pb.PbFieldType.O3)\n    ..a<$core.int>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'connectionsOut', $pb.PbFieldType.O3)\n    ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'trafficAvailable')\n    ..aInt64(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'uplink')\n    ..aInt64(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'downlink')\n    ..aInt64(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'uplinkTotal')\n    ..aInt64(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'downlinkTotal')\n    ..aOS(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'currentOutbound')\n    ..aOS(11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'currentProfile')\n    ..hasRequiredFields = false\n  ;\n\n  SystemInfo._() : super();\n  factory SystemInfo({\n    $fixnum.Int64? memory,\n    $core.int? goroutines,\n    $core.int? connectionsIn,\n    $core.int? connectionsOut,\n    $core.bool? trafficAvailable,\n    $fixnum.Int64? uplink,\n    $fixnum.Int64? downlink,\n    $fixnum.Int64? uplinkTotal,\n    $fixnum.Int64? downlinkTotal,\n    $core.String? currentOutbound,\n    $core.String? currentProfile,\n  }) {\n    final _result = create();\n    if (memory != null) {\n      _result.memory = memory;\n    }\n    if (goroutines != null) {\n      _result.goroutines = goroutines;\n    }\n    if (connectionsIn != null) {\n      _result.connectionsIn = connectionsIn;\n    }\n    if (connectionsOut != null) {\n      _result.connectionsOut = connectionsOut;\n    }\n    if (trafficAvailable != null) {\n      _result.trafficAvailable = trafficAvailable;\n    }\n    if (uplink != null) {\n      _result.uplink = uplink;\n    }\n    if (downlink != null) {\n      _result.downlink = downlink;\n    }\n    if (uplinkTotal != null) {\n      _result.uplinkTotal = uplinkTotal;\n    }\n    if (downlinkTotal != null) {\n      _result.downlinkTotal = downlinkTotal;\n    }\n    if (currentOutbound != null) {\n      _result.currentOutbound = currentOutbound;\n    }\n    if (currentProfile != null) {\n      _result.currentProfile = currentProfile;\n    }\n    return _result;\n  }\n  factory SystemInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory SystemInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  SystemInfo clone() => SystemInfo()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  SystemInfo copyWith(void Function(SystemInfo) updates) => super.copyWith((message) => updates(message as SystemInfo)) as SystemInfo; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static SystemInfo create() => SystemInfo._();\n  SystemInfo createEmptyInstance() => create();\n  static $pb.PbList<SystemInfo> createRepeated() => $pb.PbList<SystemInfo>();\n  @$core.pragma('dart2js:noInline')\n  static SystemInfo getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SystemInfo>(create);\n  static SystemInfo? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $fixnum.Int64 get memory => $_getI64(0);\n  @$pb.TagNumber(1)\n  set memory($fixnum.Int64 v) { $_setInt64(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasMemory() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearMemory() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.int get goroutines => $_getIZ(1);\n  @$pb.TagNumber(2)\n  set goroutines($core.int v) { $_setSignedInt32(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasGoroutines() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearGoroutines() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.int get connectionsIn => $_getIZ(2);\n  @$pb.TagNumber(3)\n  set connectionsIn($core.int v) { $_setSignedInt32(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasConnectionsIn() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearConnectionsIn() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.int get connectionsOut => $_getIZ(3);\n  @$pb.TagNumber(4)\n  set connectionsOut($core.int v) { $_setSignedInt32(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasConnectionsOut() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearConnectionsOut() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.bool get trafficAvailable => $_getBF(4);\n  @$pb.TagNumber(5)\n  set trafficAvailable($core.bool v) { $_setBool(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasTrafficAvailable() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearTrafficAvailable() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $fixnum.Int64 get uplink => $_getI64(5);\n  @$pb.TagNumber(6)\n  set uplink($fixnum.Int64 v) { $_setInt64(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasUplink() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearUplink() => clearField(6);\n\n  @$pb.TagNumber(7)\n  $fixnum.Int64 get downlink => $_getI64(6);\n  @$pb.TagNumber(7)\n  set downlink($fixnum.Int64 v) { $_setInt64(6, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasDownlink() => $_has(6);\n  @$pb.TagNumber(7)\n  void clearDownlink() => clearField(7);\n\n  @$pb.TagNumber(8)\n  $fixnum.Int64 get uplinkTotal => $_getI64(7);\n  @$pb.TagNumber(8)\n  set uplinkTotal($fixnum.Int64 v) { $_setInt64(7, v); }\n  @$pb.TagNumber(8)\n  $core.bool hasUplinkTotal() => $_has(7);\n  @$pb.TagNumber(8)\n  void clearUplinkTotal() => clearField(8);\n\n  @$pb.TagNumber(9)\n  $fixnum.Int64 get downlinkTotal => $_getI64(8);\n  @$pb.TagNumber(9)\n  set downlinkTotal($fixnum.Int64 v) { $_setInt64(8, v); }\n  @$pb.TagNumber(9)\n  $core.bool hasDownlinkTotal() => $_has(8);\n  @$pb.TagNumber(9)\n  void clearDownlinkTotal() => clearField(9);\n\n  @$pb.TagNumber(10)\n  $core.String get currentOutbound => $_getSZ(9);\n  @$pb.TagNumber(10)\n  set currentOutbound($core.String v) { $_setString(9, v); }\n  @$pb.TagNumber(10)\n  $core.bool hasCurrentOutbound() => $_has(9);\n  @$pb.TagNumber(10)\n  void clearCurrentOutbound() => clearField(10);\n\n  @$pb.TagNumber(11)\n  $core.String get currentProfile => $_getSZ(10);\n  @$pb.TagNumber(11)\n  set currentProfile($core.String v) { $_setString(10, v); }\n  @$pb.TagNumber(11)\n  $core.bool hasCurrentProfile() => $_has(10);\n  @$pb.TagNumber(11)\n  void clearCurrentProfile() => clearField(11);\n}\n\nclass OutboundInfo extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'OutboundInfo', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'tag')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'type')\n    ..aOM<$7.Timestamp>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'urlTestTime', subBuilder: $7.Timestamp.create)\n    ..a<$core.int>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'urlTestDelay', $pb.PbFieldType.O3)\n    ..aOM<IpInfo>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ipinfo', subBuilder: IpInfo.create)\n    ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isSelected')\n    ..aOB(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isGroup')\n    ..aOB(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isSecure')\n    ..aOB(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isVisible')\n    ..a<$core.int>(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'port', $pb.PbFieldType.OU3)\n    ..aOS(11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'host')\n    ..aOS(12, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'tagDisplay')\n    ..aOS(13, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'groupSelectedTag')\n    ..aOS(14, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'groupSelectedTagDisplay')\n    ..aInt64(15, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'upload')\n    ..aInt64(16, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'download')\n    ..hasRequiredFields = false\n  ;\n\n  OutboundInfo._() : super();\n  factory OutboundInfo({\n    $core.String? tag,\n    $core.String? type,\n    $7.Timestamp? urlTestTime,\n    $core.int? urlTestDelay,\n    IpInfo? ipinfo,\n    $core.bool? isSelected,\n    $core.bool? isGroup,\n    $core.bool? isSecure,\n    $core.bool? isVisible,\n    $core.int? port,\n    $core.String? host,\n    $core.String? tagDisplay,\n    $core.String? groupSelectedTag,\n    $core.String? groupSelectedTagDisplay,\n    $fixnum.Int64? upload,\n    $fixnum.Int64? download,\n  }) {\n    final _result = create();\n    if (tag != null) {\n      _result.tag = tag;\n    }\n    if (type != null) {\n      _result.type = type;\n    }\n    if (urlTestTime != null) {\n      _result.urlTestTime = urlTestTime;\n    }\n    if (urlTestDelay != null) {\n      _result.urlTestDelay = urlTestDelay;\n    }\n    if (ipinfo != null) {\n      _result.ipinfo = ipinfo;\n    }\n    if (isSelected != null) {\n      _result.isSelected = isSelected;\n    }\n    if (isGroup != null) {\n      _result.isGroup = isGroup;\n    }\n    if (isSecure != null) {\n      _result.isSecure = isSecure;\n    }\n    if (isVisible != null) {\n      _result.isVisible = isVisible;\n    }\n    if (port != null) {\n      _result.port = port;\n    }\n    if (host != null) {\n      _result.host = host;\n    }\n    if (tagDisplay != null) {\n      _result.tagDisplay = tagDisplay;\n    }\n    if (groupSelectedTag != null) {\n      _result.groupSelectedTag = groupSelectedTag;\n    }\n    if (groupSelectedTagDisplay != null) {\n      _result.groupSelectedTagDisplay = groupSelectedTagDisplay;\n    }\n    if (upload != null) {\n      _result.upload = upload;\n    }\n    if (download != null) {\n      _result.download = download;\n    }\n    return _result;\n  }\n  factory OutboundInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory OutboundInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  OutboundInfo clone() => OutboundInfo()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  OutboundInfo copyWith(void Function(OutboundInfo) updates) => super.copyWith((message) => updates(message as OutboundInfo)) as OutboundInfo; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static OutboundInfo create() => OutboundInfo._();\n  OutboundInfo createEmptyInstance() => create();\n  static $pb.PbList<OutboundInfo> createRepeated() => $pb.PbList<OutboundInfo>();\n  @$core.pragma('dart2js:noInline')\n  static OutboundInfo getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<OutboundInfo>(create);\n  static OutboundInfo? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get tag => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set tag($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasTag() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearTag() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get type => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set type($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasType() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearType() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $7.Timestamp get urlTestTime => $_getN(2);\n  @$pb.TagNumber(3)\n  set urlTestTime($7.Timestamp v) { setField(3, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasUrlTestTime() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearUrlTestTime() => clearField(3);\n  @$pb.TagNumber(3)\n  $7.Timestamp ensureUrlTestTime() => $_ensure(2);\n\n  @$pb.TagNumber(4)\n  $core.int get urlTestDelay => $_getIZ(3);\n  @$pb.TagNumber(4)\n  set urlTestDelay($core.int v) { $_setSignedInt32(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasUrlTestDelay() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearUrlTestDelay() => clearField(4);\n\n  @$pb.TagNumber(5)\n  IpInfo get ipinfo => $_getN(4);\n  @$pb.TagNumber(5)\n  set ipinfo(IpInfo v) { setField(5, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasIpinfo() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearIpinfo() => clearField(5);\n  @$pb.TagNumber(5)\n  IpInfo ensureIpinfo() => $_ensure(4);\n\n  @$pb.TagNumber(6)\n  $core.bool get isSelected => $_getBF(5);\n  @$pb.TagNumber(6)\n  set isSelected($core.bool v) { $_setBool(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasIsSelected() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearIsSelected() => clearField(6);\n\n  @$pb.TagNumber(7)\n  $core.bool get isGroup => $_getBF(6);\n  @$pb.TagNumber(7)\n  set isGroup($core.bool v) { $_setBool(6, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasIsGroup() => $_has(6);\n  @$pb.TagNumber(7)\n  void clearIsGroup() => clearField(7);\n\n  @$pb.TagNumber(8)\n  $core.bool get isSecure => $_getBF(7);\n  @$pb.TagNumber(8)\n  set isSecure($core.bool v) { $_setBool(7, v); }\n  @$pb.TagNumber(8)\n  $core.bool hasIsSecure() => $_has(7);\n  @$pb.TagNumber(8)\n  void clearIsSecure() => clearField(8);\n\n  @$pb.TagNumber(9)\n  $core.bool get isVisible => $_getBF(8);\n  @$pb.TagNumber(9)\n  set isVisible($core.bool v) { $_setBool(8, v); }\n  @$pb.TagNumber(9)\n  $core.bool hasIsVisible() => $_has(8);\n  @$pb.TagNumber(9)\n  void clearIsVisible() => clearField(9);\n\n  @$pb.TagNumber(10)\n  $core.int get port => $_getIZ(9);\n  @$pb.TagNumber(10)\n  set port($core.int v) { $_setUnsignedInt32(9, v); }\n  @$pb.TagNumber(10)\n  $core.bool hasPort() => $_has(9);\n  @$pb.TagNumber(10)\n  void clearPort() => clearField(10);\n\n  @$pb.TagNumber(11)\n  $core.String get host => $_getSZ(10);\n  @$pb.TagNumber(11)\n  set host($core.String v) { $_setString(10, v); }\n  @$pb.TagNumber(11)\n  $core.bool hasHost() => $_has(10);\n  @$pb.TagNumber(11)\n  void clearHost() => clearField(11);\n\n  @$pb.TagNumber(12)\n  $core.String get tagDisplay => $_getSZ(11);\n  @$pb.TagNumber(12)\n  set tagDisplay($core.String v) { $_setString(11, v); }\n  @$pb.TagNumber(12)\n  $core.bool hasTagDisplay() => $_has(11);\n  @$pb.TagNumber(12)\n  void clearTagDisplay() => clearField(12);\n\n  @$pb.TagNumber(13)\n  $core.String get groupSelectedTag => $_getSZ(12);\n  @$pb.TagNumber(13)\n  set groupSelectedTag($core.String v) { $_setString(12, v); }\n  @$pb.TagNumber(13)\n  $core.bool hasGroupSelectedTag() => $_has(12);\n  @$pb.TagNumber(13)\n  void clearGroupSelectedTag() => clearField(13);\n\n  @$pb.TagNumber(14)\n  $core.String get groupSelectedTagDisplay => $_getSZ(13);\n  @$pb.TagNumber(14)\n  set groupSelectedTagDisplay($core.String v) { $_setString(13, v); }\n  @$pb.TagNumber(14)\n  $core.bool hasGroupSelectedTagDisplay() => $_has(13);\n  @$pb.TagNumber(14)\n  void clearGroupSelectedTagDisplay() => clearField(14);\n\n  @$pb.TagNumber(15)\n  $fixnum.Int64 get upload => $_getI64(14);\n  @$pb.TagNumber(15)\n  set upload($fixnum.Int64 v) { $_setInt64(14, v); }\n  @$pb.TagNumber(15)\n  $core.bool hasUpload() => $_has(14);\n  @$pb.TagNumber(15)\n  void clearUpload() => clearField(15);\n\n  @$pb.TagNumber(16)\n  $fixnum.Int64 get download => $_getI64(15);\n  @$pb.TagNumber(16)\n  set download($fixnum.Int64 v) { $_setInt64(15, v); }\n  @$pb.TagNumber(16)\n  $core.bool hasDownload() => $_has(15);\n  @$pb.TagNumber(16)\n  void clearDownload() => clearField(16);\n}\n\nclass IpInfo extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'IpInfo', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ip')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'country_code')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'region')\n    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'city')\n    ..a<$core.int>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'asn', $pb.PbFieldType.O3)\n    ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'org')\n    ..a<$core.double>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'latitude', $pb.PbFieldType.OD)\n    ..a<$core.double>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'longitude', $pb.PbFieldType.OD)\n    ..aOS(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'postal_code')\n    ..hasRequiredFields = false\n  ;\n\n  IpInfo._() : super();\n  factory IpInfo({\n    $core.String? ip,\n    $core.String? countryCode,\n    $core.String? region,\n    $core.String? city,\n    $core.int? asn,\n    $core.String? org,\n    $core.double? latitude,\n    $core.double? longitude,\n    $core.String? postalCode,\n  }) {\n    final _result = create();\n    if (ip != null) {\n      _result.ip = ip;\n    }\n    if (countryCode != null) {\n      _result.countryCode = countryCode;\n    }\n    if (region != null) {\n      _result.region = region;\n    }\n    if (city != null) {\n      _result.city = city;\n    }\n    if (asn != null) {\n      _result.asn = asn;\n    }\n    if (org != null) {\n      _result.org = org;\n    }\n    if (latitude != null) {\n      _result.latitude = latitude;\n    }\n    if (longitude != null) {\n      _result.longitude = longitude;\n    }\n    if (postalCode != null) {\n      _result.postalCode = postalCode;\n    }\n    return _result;\n  }\n  factory IpInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory IpInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  IpInfo clone() => IpInfo()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  IpInfo copyWith(void Function(IpInfo) updates) => super.copyWith((message) => updates(message as IpInfo)) as IpInfo; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static IpInfo create() => IpInfo._();\n  IpInfo createEmptyInstance() => create();\n  static $pb.PbList<IpInfo> createRepeated() => $pb.PbList<IpInfo>();\n  @$core.pragma('dart2js:noInline')\n  static IpInfo getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<IpInfo>(create);\n  static IpInfo? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get ip => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set ip($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasIp() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearIp() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get countryCode => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set countryCode($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasCountryCode() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearCountryCode() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get region => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set region($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasRegion() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearRegion() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.String get city => $_getSZ(3);\n  @$pb.TagNumber(4)\n  set city($core.String v) { $_setString(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasCity() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearCity() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.int get asn => $_getIZ(4);\n  @$pb.TagNumber(5)\n  set asn($core.int v) { $_setSignedInt32(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasAsn() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearAsn() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $core.String get org => $_getSZ(5);\n  @$pb.TagNumber(6)\n  set org($core.String v) { $_setString(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasOrg() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearOrg() => clearField(6);\n\n  @$pb.TagNumber(7)\n  $core.double get latitude => $_getN(6);\n  @$pb.TagNumber(7)\n  set latitude($core.double v) { $_setDouble(6, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasLatitude() => $_has(6);\n  @$pb.TagNumber(7)\n  void clearLatitude() => clearField(7);\n\n  @$pb.TagNumber(8)\n  $core.double get longitude => $_getN(7);\n  @$pb.TagNumber(8)\n  set longitude($core.double v) { $_setDouble(7, v); }\n  @$pb.TagNumber(8)\n  $core.bool hasLongitude() => $_has(7);\n  @$pb.TagNumber(8)\n  void clearLongitude() => clearField(8);\n\n  @$pb.TagNumber(9)\n  $core.String get postalCode => $_getSZ(8);\n  @$pb.TagNumber(9)\n  set postalCode($core.String v) { $_setString(8, v); }\n  @$pb.TagNumber(9)\n  $core.bool hasPostalCode() => $_has(8);\n  @$pb.TagNumber(9)\n  void clearPostalCode() => clearField(9);\n}\n\nclass OutboundGroup extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'OutboundGroup', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'tag')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'type')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'selected')\n    ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'selectable')\n    ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'IsExpand', protoName: 'Is_expand')\n    ..pc<OutboundInfo>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: OutboundInfo.create)\n    ..hasRequiredFields = false\n  ;\n\n  OutboundGroup._() : super();\n  factory OutboundGroup({\n    $core.String? tag,\n    $core.String? type,\n    $core.String? selected,\n    $core.bool? selectable,\n    $core.bool? isExpand,\n    $core.Iterable<OutboundInfo>? items,\n  }) {\n    final _result = create();\n    if (tag != null) {\n      _result.tag = tag;\n    }\n    if (type != null) {\n      _result.type = type;\n    }\n    if (selected != null) {\n      _result.selected = selected;\n    }\n    if (selectable != null) {\n      _result.selectable = selectable;\n    }\n    if (isExpand != null) {\n      _result.isExpand = isExpand;\n    }\n    if (items != null) {\n      _result.items.addAll(items);\n    }\n    return _result;\n  }\n  factory OutboundGroup.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory OutboundGroup.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  OutboundGroup clone() => OutboundGroup()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  OutboundGroup copyWith(void Function(OutboundGroup) updates) => super.copyWith((message) => updates(message as OutboundGroup)) as OutboundGroup; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static OutboundGroup create() => OutboundGroup._();\n  OutboundGroup createEmptyInstance() => create();\n  static $pb.PbList<OutboundGroup> createRepeated() => $pb.PbList<OutboundGroup>();\n  @$core.pragma('dart2js:noInline')\n  static OutboundGroup getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<OutboundGroup>(create);\n  static OutboundGroup? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get tag => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set tag($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasTag() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearTag() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get type => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set type($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasType() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearType() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get selected => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set selected($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasSelected() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearSelected() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.bool get selectable => $_getBF(3);\n  @$pb.TagNumber(4)\n  set selectable($core.bool v) { $_setBool(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasSelectable() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearSelectable() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.bool get isExpand => $_getBF(4);\n  @$pb.TagNumber(5)\n  set isExpand($core.bool v) { $_setBool(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasIsExpand() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearIsExpand() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $core.List<OutboundInfo> get items => $_getList(5);\n}\n\nclass OutboundGroupList extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'OutboundGroupList', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..pc<OutboundGroup>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: OutboundGroup.create)\n    ..hasRequiredFields = false\n  ;\n\n  OutboundGroupList._() : super();\n  factory OutboundGroupList({\n    $core.Iterable<OutboundGroup>? items,\n  }) {\n    final _result = create();\n    if (items != null) {\n      _result.items.addAll(items);\n    }\n    return _result;\n  }\n  factory OutboundGroupList.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory OutboundGroupList.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  OutboundGroupList clone() => OutboundGroupList()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  OutboundGroupList copyWith(void Function(OutboundGroupList) updates) => super.copyWith((message) => updates(message as OutboundGroupList)) as OutboundGroupList; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static OutboundGroupList create() => OutboundGroupList._();\n  OutboundGroupList createEmptyInstance() => create();\n  static $pb.PbList<OutboundGroupList> createRepeated() => $pb.PbList<OutboundGroupList>();\n  @$core.pragma('dart2js:noInline')\n  static OutboundGroupList getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<OutboundGroupList>(create);\n  static OutboundGroupList? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.List<OutboundGroup> get items => $_getList(0);\n}\n\nclass WarpAccount extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WarpAccount', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'accountId')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'accessToken')\n    ..hasRequiredFields = false\n  ;\n\n  WarpAccount._() : super();\n  factory WarpAccount({\n    $core.String? accountId,\n    $core.String? accessToken,\n  }) {\n    final _result = create();\n    if (accountId != null) {\n      _result.accountId = accountId;\n    }\n    if (accessToken != null) {\n      _result.accessToken = accessToken;\n    }\n    return _result;\n  }\n  factory WarpAccount.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory WarpAccount.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  WarpAccount clone() => WarpAccount()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  WarpAccount copyWith(void Function(WarpAccount) updates) => super.copyWith((message) => updates(message as WarpAccount)) as WarpAccount; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static WarpAccount create() => WarpAccount._();\n  WarpAccount createEmptyInstance() => create();\n  static $pb.PbList<WarpAccount> createRepeated() => $pb.PbList<WarpAccount>();\n  @$core.pragma('dart2js:noInline')\n  static WarpAccount getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<WarpAccount>(create);\n  static WarpAccount? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get accountId => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set accountId($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasAccountId() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearAccountId() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get accessToken => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set accessToken($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasAccessToken() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearAccessToken() => clearField(2);\n}\n\nclass WarpWireguardConfig extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WarpWireguardConfig', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'private-key', protoName: 'private_key')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'local-address-ipv4', protoName: 'local_address_ipv4')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'local-address-ipv6', protoName: 'local_address_ipv6')\n    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'peer-public-key', protoName: 'peer_public_key')\n    ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'client-id', protoName: 'client_id')\n    ..hasRequiredFields = false\n  ;\n\n  WarpWireguardConfig._() : super();\n  factory WarpWireguardConfig({\n    $core.String? privateKey,\n    $core.String? localAddressIpv4,\n    $core.String? localAddressIpv6,\n    $core.String? peerPublicKey,\n    $core.String? clientId,\n  }) {\n    final _result = create();\n    if (privateKey != null) {\n      _result.privateKey = privateKey;\n    }\n    if (localAddressIpv4 != null) {\n      _result.localAddressIpv4 = localAddressIpv4;\n    }\n    if (localAddressIpv6 != null) {\n      _result.localAddressIpv6 = localAddressIpv6;\n    }\n    if (peerPublicKey != null) {\n      _result.peerPublicKey = peerPublicKey;\n    }\n    if (clientId != null) {\n      _result.clientId = clientId;\n    }\n    return _result;\n  }\n  factory WarpWireguardConfig.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory WarpWireguardConfig.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  WarpWireguardConfig clone() => WarpWireguardConfig()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  WarpWireguardConfig copyWith(void Function(WarpWireguardConfig) updates) => super.copyWith((message) => updates(message as WarpWireguardConfig)) as WarpWireguardConfig; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static WarpWireguardConfig create() => WarpWireguardConfig._();\n  WarpWireguardConfig createEmptyInstance() => create();\n  static $pb.PbList<WarpWireguardConfig> createRepeated() => $pb.PbList<WarpWireguardConfig>();\n  @$core.pragma('dart2js:noInline')\n  static WarpWireguardConfig getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<WarpWireguardConfig>(create);\n  static WarpWireguardConfig? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get privateKey => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set privateKey($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasPrivateKey() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearPrivateKey() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get localAddressIpv4 => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set localAddressIpv4($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasLocalAddressIpv4() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearLocalAddressIpv4() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get localAddressIpv6 => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set localAddressIpv6($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasLocalAddressIpv6() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearLocalAddressIpv6() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.String get peerPublicKey => $_getSZ(3);\n  @$pb.TagNumber(4)\n  set peerPublicKey($core.String v) { $_setString(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasPeerPublicKey() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearPeerPublicKey() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.String get clientId => $_getSZ(4);\n  @$pb.TagNumber(5)\n  set clientId($core.String v) { $_setString(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasClientId() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearClientId() => clearField(5);\n}\n\nclass WarpGenerationResponse extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WarpGenerationResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOM<WarpAccount>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'account', subBuilder: WarpAccount.create)\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'log')\n    ..aOM<WarpWireguardConfig>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'config', subBuilder: WarpWireguardConfig.create)\n    ..hasRequiredFields = false\n  ;\n\n  WarpGenerationResponse._() : super();\n  factory WarpGenerationResponse({\n    WarpAccount? account,\n    $core.String? log,\n    WarpWireguardConfig? config,\n  }) {\n    final _result = create();\n    if (account != null) {\n      _result.account = account;\n    }\n    if (log != null) {\n      _result.log = log;\n    }\n    if (config != null) {\n      _result.config = config;\n    }\n    return _result;\n  }\n  factory WarpGenerationResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory WarpGenerationResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  WarpGenerationResponse clone() => WarpGenerationResponse()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  WarpGenerationResponse copyWith(void Function(WarpGenerationResponse) updates) => super.copyWith((message) => updates(message as WarpGenerationResponse)) as WarpGenerationResponse; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static WarpGenerationResponse create() => WarpGenerationResponse._();\n  WarpGenerationResponse createEmptyInstance() => create();\n  static $pb.PbList<WarpGenerationResponse> createRepeated() => $pb.PbList<WarpGenerationResponse>();\n  @$core.pragma('dart2js:noInline')\n  static WarpGenerationResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<WarpGenerationResponse>(create);\n  static WarpGenerationResponse? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  WarpAccount get account => $_getN(0);\n  @$pb.TagNumber(1)\n  set account(WarpAccount v) { setField(1, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasAccount() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearAccount() => clearField(1);\n  @$pb.TagNumber(1)\n  WarpAccount ensureAccount() => $_ensure(0);\n\n  @$pb.TagNumber(2)\n  $core.String get log => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set log($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasLog() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearLog() => clearField(2);\n\n  @$pb.TagNumber(3)\n  WarpWireguardConfig get config => $_getN(2);\n  @$pb.TagNumber(3)\n  set config(WarpWireguardConfig v) { setField(3, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasConfig() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearConfig() => clearField(3);\n  @$pb.TagNumber(3)\n  WarpWireguardConfig ensureConfig() => $_ensure(2);\n}\n\nclass SystemProxyStatus extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SystemProxyStatus', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'available')\n    ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enabled')\n    ..hasRequiredFields = false\n  ;\n\n  SystemProxyStatus._() : super();\n  factory SystemProxyStatus({\n    $core.bool? available,\n    $core.bool? enabled,\n  }) {\n    final _result = create();\n    if (available != null) {\n      _result.available = available;\n    }\n    if (enabled != null) {\n      _result.enabled = enabled;\n    }\n    return _result;\n  }\n  factory SystemProxyStatus.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory SystemProxyStatus.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  SystemProxyStatus clone() => SystemProxyStatus()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  SystemProxyStatus copyWith(void Function(SystemProxyStatus) updates) => super.copyWith((message) => updates(message as SystemProxyStatus)) as SystemProxyStatus; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static SystemProxyStatus create() => SystemProxyStatus._();\n  SystemProxyStatus createEmptyInstance() => create();\n  static $pb.PbList<SystemProxyStatus> createRepeated() => $pb.PbList<SystemProxyStatus>();\n  @$core.pragma('dart2js:noInline')\n  static SystemProxyStatus getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SystemProxyStatus>(create);\n  static SystemProxyStatus? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.bool get available => $_getBF(0);\n  @$pb.TagNumber(1)\n  set available($core.bool v) { $_setBool(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasAvailable() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearAvailable() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.bool get enabled => $_getBF(1);\n  @$pb.TagNumber(2)\n  set enabled($core.bool v) { $_setBool(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasEnabled() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearEnabled() => clearField(2);\n}\n\nclass ParseRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ParseRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'content')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'configPath')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'tempPath')\n    ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'debug')\n    ..hasRequiredFields = false\n  ;\n\n  ParseRequest._() : super();\n  factory ParseRequest({\n    $core.String? content,\n    $core.String? configPath,\n    $core.String? tempPath,\n    $core.bool? debug,\n  }) {\n    final _result = create();\n    if (content != null) {\n      _result.content = content;\n    }\n    if (configPath != null) {\n      _result.configPath = configPath;\n    }\n    if (tempPath != null) {\n      _result.tempPath = tempPath;\n    }\n    if (debug != null) {\n      _result.debug = debug;\n    }\n    return _result;\n  }\n  factory ParseRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ParseRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ParseRequest clone() => ParseRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ParseRequest copyWith(void Function(ParseRequest) updates) => super.copyWith((message) => updates(message as ParseRequest)) as ParseRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ParseRequest create() => ParseRequest._();\n  ParseRequest createEmptyInstance() => create();\n  static $pb.PbList<ParseRequest> createRepeated() => $pb.PbList<ParseRequest>();\n  @$core.pragma('dart2js:noInline')\n  static ParseRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ParseRequest>(create);\n  static ParseRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get content => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set content($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasContent() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearContent() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get configPath => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set configPath($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasConfigPath() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearConfigPath() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get tempPath => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set tempPath($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasTempPath() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearTempPath() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.bool get debug => $_getBF(3);\n  @$pb.TagNumber(4)\n  set debug($core.bool v) { $_setBool(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasDebug() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearDebug() => clearField(4);\n}\n\nclass ParseResponse extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ParseResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..e<$1.ResponseCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'responseCode', $pb.PbFieldType.OE, defaultOrMaker: $1.ResponseCode.OK, valueOf: $1.ResponseCode.valueOf, enumValues: $1.ResponseCode.values)\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'content')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message')\n    ..hasRequiredFields = false\n  ;\n\n  ParseResponse._() : super();\n  factory ParseResponse({\n    $1.ResponseCode? responseCode,\n    $core.String? content,\n    $core.String? message,\n  }) {\n    final _result = create();\n    if (responseCode != null) {\n      _result.responseCode = responseCode;\n    }\n    if (content != null) {\n      _result.content = content;\n    }\n    if (message != null) {\n      _result.message = message;\n    }\n    return _result;\n  }\n  factory ParseResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ParseResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ParseResponse clone() => ParseResponse()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ParseResponse copyWith(void Function(ParseResponse) updates) => super.copyWith((message) => updates(message as ParseResponse)) as ParseResponse; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ParseResponse create() => ParseResponse._();\n  ParseResponse createEmptyInstance() => create();\n  static $pb.PbList<ParseResponse> createRepeated() => $pb.PbList<ParseResponse>();\n  @$core.pragma('dart2js:noInline')\n  static ParseResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ParseResponse>(create);\n  static ParseResponse? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $1.ResponseCode get responseCode => $_getN(0);\n  @$pb.TagNumber(1)\n  set responseCode($1.ResponseCode v) { setField(1, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasResponseCode() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearResponseCode() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get content => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set content($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasContent() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearContent() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get message => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set message($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasMessage() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearMessage() => clearField(3);\n}\n\nclass ChangeHiddifySettingsRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ChangeHiddifySettingsRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'hiddifySettingsJson')\n    ..hasRequiredFields = false\n  ;\n\n  ChangeHiddifySettingsRequest._() : super();\n  factory ChangeHiddifySettingsRequest({\n    $core.String? hiddifySettingsJson,\n  }) {\n    final _result = create();\n    if (hiddifySettingsJson != null) {\n      _result.hiddifySettingsJson = hiddifySettingsJson;\n    }\n    return _result;\n  }\n  factory ChangeHiddifySettingsRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ChangeHiddifySettingsRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ChangeHiddifySettingsRequest clone() => ChangeHiddifySettingsRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ChangeHiddifySettingsRequest copyWith(void Function(ChangeHiddifySettingsRequest) updates) => super.copyWith((message) => updates(message as ChangeHiddifySettingsRequest)) as ChangeHiddifySettingsRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ChangeHiddifySettingsRequest create() => ChangeHiddifySettingsRequest._();\n  ChangeHiddifySettingsRequest createEmptyInstance() => create();\n  static $pb.PbList<ChangeHiddifySettingsRequest> createRepeated() => $pb.PbList<ChangeHiddifySettingsRequest>();\n  @$core.pragma('dart2js:noInline')\n  static ChangeHiddifySettingsRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ChangeHiddifySettingsRequest>(create);\n  static ChangeHiddifySettingsRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get hiddifySettingsJson => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set hiddifySettingsJson($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasHiddifySettingsJson() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearHiddifySettingsJson() => clearField(1);\n}\n\nclass GenerateConfigRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GenerateConfigRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'path')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'tempPath')\n    ..aOB(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'debug')\n    ..hasRequiredFields = false\n  ;\n\n  GenerateConfigRequest._() : super();\n  factory GenerateConfigRequest({\n    $core.String? path,\n    $core.String? tempPath,\n    $core.bool? debug,\n  }) {\n    final _result = create();\n    if (path != null) {\n      _result.path = path;\n    }\n    if (tempPath != null) {\n      _result.tempPath = tempPath;\n    }\n    if (debug != null) {\n      _result.debug = debug;\n    }\n    return _result;\n  }\n  factory GenerateConfigRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory GenerateConfigRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  GenerateConfigRequest clone() => GenerateConfigRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  GenerateConfigRequest copyWith(void Function(GenerateConfigRequest) updates) => super.copyWith((message) => updates(message as GenerateConfigRequest)) as GenerateConfigRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static GenerateConfigRequest create() => GenerateConfigRequest._();\n  GenerateConfigRequest createEmptyInstance() => create();\n  static $pb.PbList<GenerateConfigRequest> createRepeated() => $pb.PbList<GenerateConfigRequest>();\n  @$core.pragma('dart2js:noInline')\n  static GenerateConfigRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GenerateConfigRequest>(create);\n  static GenerateConfigRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get path => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set path($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasPath() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearPath() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get tempPath => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set tempPath($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasTempPath() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearTempPath() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.bool get debug => $_getBF(2);\n  @$pb.TagNumber(3)\n  set debug($core.bool v) { $_setBool(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasDebug() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearDebug() => clearField(3);\n}\n\nclass GenerateConfigResponse extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GenerateConfigResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'configContent')\n    ..hasRequiredFields = false\n  ;\n\n  GenerateConfigResponse._() : super();\n  factory GenerateConfigResponse({\n    $core.String? configContent,\n  }) {\n    final _result = create();\n    if (configContent != null) {\n      _result.configContent = configContent;\n    }\n    return _result;\n  }\n  factory GenerateConfigResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory GenerateConfigResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  GenerateConfigResponse clone() => GenerateConfigResponse()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  GenerateConfigResponse copyWith(void Function(GenerateConfigResponse) updates) => super.copyWith((message) => updates(message as GenerateConfigResponse)) as GenerateConfigResponse; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static GenerateConfigResponse create() => GenerateConfigResponse._();\n  GenerateConfigResponse createEmptyInstance() => create();\n  static $pb.PbList<GenerateConfigResponse> createRepeated() => $pb.PbList<GenerateConfigResponse>();\n  @$core.pragma('dart2js:noInline')\n  static GenerateConfigResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GenerateConfigResponse>(create);\n  static GenerateConfigResponse? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get configContent => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set configContent($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasConfigContent() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearConfigContent() => clearField(1);\n}\n\nclass SelectOutboundRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOutboundRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'groupTag')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'outboundTag')\n    ..hasRequiredFields = false\n  ;\n\n  SelectOutboundRequest._() : super();\n  factory SelectOutboundRequest({\n    $core.String? groupTag,\n    $core.String? outboundTag,\n  }) {\n    final _result = create();\n    if (groupTag != null) {\n      _result.groupTag = groupTag;\n    }\n    if (outboundTag != null) {\n      _result.outboundTag = outboundTag;\n    }\n    return _result;\n  }\n  factory SelectOutboundRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory SelectOutboundRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  SelectOutboundRequest clone() => SelectOutboundRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  SelectOutboundRequest copyWith(void Function(SelectOutboundRequest) updates) => super.copyWith((message) => updates(message as SelectOutboundRequest)) as SelectOutboundRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static SelectOutboundRequest create() => SelectOutboundRequest._();\n  SelectOutboundRequest createEmptyInstance() => create();\n  static $pb.PbList<SelectOutboundRequest> createRepeated() => $pb.PbList<SelectOutboundRequest>();\n  @$core.pragma('dart2js:noInline')\n  static SelectOutboundRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SelectOutboundRequest>(create);\n  static SelectOutboundRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get groupTag => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set groupTag($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasGroupTag() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearGroupTag() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get outboundTag => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set outboundTag($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasOutboundTag() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearOutboundTag() => clearField(2);\n}\n\nclass UrlTestRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UrlTestRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'tag')\n    ..hasRequiredFields = false\n  ;\n\n  UrlTestRequest._() : super();\n  factory UrlTestRequest({\n    $core.String? tag,\n  }) {\n    final _result = create();\n    if (tag != null) {\n      _result.tag = tag;\n    }\n    return _result;\n  }\n  factory UrlTestRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory UrlTestRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  UrlTestRequest clone() => UrlTestRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  UrlTestRequest copyWith(void Function(UrlTestRequest) updates) => super.copyWith((message) => updates(message as UrlTestRequest)) as UrlTestRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static UrlTestRequest create() => UrlTestRequest._();\n  UrlTestRequest createEmptyInstance() => create();\n  static $pb.PbList<UrlTestRequest> createRepeated() => $pb.PbList<UrlTestRequest>();\n  @$core.pragma('dart2js:noInline')\n  static UrlTestRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<UrlTestRequest>(create);\n  static UrlTestRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get tag => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set tag($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasTag() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearTag() => clearField(1);\n}\n\nclass GenerateWarpConfigRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GenerateWarpConfigRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'licenseKey')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'accountId')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'accessToken')\n    ..hasRequiredFields = false\n  ;\n\n  GenerateWarpConfigRequest._() : super();\n  factory GenerateWarpConfigRequest({\n    $core.String? licenseKey,\n    $core.String? accountId,\n    $core.String? accessToken,\n  }) {\n    final _result = create();\n    if (licenseKey != null) {\n      _result.licenseKey = licenseKey;\n    }\n    if (accountId != null) {\n      _result.accountId = accountId;\n    }\n    if (accessToken != null) {\n      _result.accessToken = accessToken;\n    }\n    return _result;\n  }\n  factory GenerateWarpConfigRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory GenerateWarpConfigRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  GenerateWarpConfigRequest clone() => GenerateWarpConfigRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  GenerateWarpConfigRequest copyWith(void Function(GenerateWarpConfigRequest) updates) => super.copyWith((message) => updates(message as GenerateWarpConfigRequest)) as GenerateWarpConfigRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static GenerateWarpConfigRequest create() => GenerateWarpConfigRequest._();\n  GenerateWarpConfigRequest createEmptyInstance() => create();\n  static $pb.PbList<GenerateWarpConfigRequest> createRepeated() => $pb.PbList<GenerateWarpConfigRequest>();\n  @$core.pragma('dart2js:noInline')\n  static GenerateWarpConfigRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GenerateWarpConfigRequest>(create);\n  static GenerateWarpConfigRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get licenseKey => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set licenseKey($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasLicenseKey() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearLicenseKey() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get accountId => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set accountId($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasAccountId() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearAccountId() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get accessToken => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set accessToken($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasAccessToken() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearAccessToken() => clearField(3);\n}\n\nclass SetSystemProxyEnabledRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SetSystemProxyEnabledRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isEnabled')\n    ..hasRequiredFields = false\n  ;\n\n  SetSystemProxyEnabledRequest._() : super();\n  factory SetSystemProxyEnabledRequest({\n    $core.bool? isEnabled,\n  }) {\n    final _result = create();\n    if (isEnabled != null) {\n      _result.isEnabled = isEnabled;\n    }\n    return _result;\n  }\n  factory SetSystemProxyEnabledRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory SetSystemProxyEnabledRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  SetSystemProxyEnabledRequest clone() => SetSystemProxyEnabledRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  SetSystemProxyEnabledRequest copyWith(void Function(SetSystemProxyEnabledRequest) updates) => super.copyWith((message) => updates(message as SetSystemProxyEnabledRequest)) as SetSystemProxyEnabledRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static SetSystemProxyEnabledRequest create() => SetSystemProxyEnabledRequest._();\n  SetSystemProxyEnabledRequest createEmptyInstance() => create();\n  static $pb.PbList<SetSystemProxyEnabledRequest> createRepeated() => $pb.PbList<SetSystemProxyEnabledRequest>();\n  @$core.pragma('dart2js:noInline')\n  static SetSystemProxyEnabledRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SetSystemProxyEnabledRequest>(create);\n  static SetSystemProxyEnabledRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.bool get isEnabled => $_getBF(0);\n  @$pb.TagNumber(1)\n  set isEnabled($core.bool v) { $_setBool(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasIsEnabled() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearIsEnabled() => clearField(1);\n}\n\nclass LogMessage extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'LogMessage', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..e<LogLevel>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'level', $pb.PbFieldType.OE, defaultOrMaker: LogLevel.TRACE, valueOf: LogLevel.valueOf, enumValues: LogLevel.values)\n    ..e<LogType>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'type', $pb.PbFieldType.OE, defaultOrMaker: LogType.CORE, valueOf: LogType.valueOf, enumValues: LogType.values)\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message')\n    ..aOM<$7.Timestamp>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'time', subBuilder: $7.Timestamp.create)\n    ..hasRequiredFields = false\n  ;\n\n  LogMessage._() : super();\n  factory LogMessage({\n    LogLevel? level,\n    LogType? type,\n    $core.String? message,\n    $7.Timestamp? time,\n  }) {\n    final _result = create();\n    if (level != null) {\n      _result.level = level;\n    }\n    if (type != null) {\n      _result.type = type;\n    }\n    if (message != null) {\n      _result.message = message;\n    }\n    if (time != null) {\n      _result.time = time;\n    }\n    return _result;\n  }\n  factory LogMessage.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory LogMessage.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  LogMessage clone() => LogMessage()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  LogMessage copyWith(void Function(LogMessage) updates) => super.copyWith((message) => updates(message as LogMessage)) as LogMessage; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static LogMessage create() => LogMessage._();\n  LogMessage createEmptyInstance() => create();\n  static $pb.PbList<LogMessage> createRepeated() => $pb.PbList<LogMessage>();\n  @$core.pragma('dart2js:noInline')\n  static LogMessage getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<LogMessage>(create);\n  static LogMessage? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  LogLevel get level => $_getN(0);\n  @$pb.TagNumber(1)\n  set level(LogLevel v) { setField(1, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasLevel() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearLevel() => clearField(1);\n\n  @$pb.TagNumber(2)\n  LogType get type => $_getN(1);\n  @$pb.TagNumber(2)\n  set type(LogType v) { setField(2, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasType() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearType() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get message => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set message($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasMessage() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearMessage() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $7.Timestamp get time => $_getN(3);\n  @$pb.TagNumber(4)\n  set time($7.Timestamp v) { setField(4, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasTime() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearTime() => clearField(4);\n  @$pb.TagNumber(4)\n  $7.Timestamp ensureTime() => $_ensure(3);\n}\n\nclass LogRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'LogRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..e<LogLevel>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'level', $pb.PbFieldType.OE, defaultOrMaker: LogLevel.TRACE, valueOf: LogLevel.valueOf, enumValues: LogLevel.values)\n    ..hasRequiredFields = false\n  ;\n\n  LogRequest._() : super();\n  factory LogRequest({\n    LogLevel? level,\n  }) {\n    final _result = create();\n    if (level != null) {\n      _result.level = level;\n    }\n    return _result;\n  }\n  factory LogRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory LogRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  LogRequest clone() => LogRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  LogRequest copyWith(void Function(LogRequest) updates) => super.copyWith((message) => updates(message as LogRequest)) as LogRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static LogRequest create() => LogRequest._();\n  LogRequest createEmptyInstance() => create();\n  static $pb.PbList<LogRequest> createRepeated() => $pb.PbList<LogRequest>();\n  @$core.pragma('dart2js:noInline')\n  static LogRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<LogRequest>(create);\n  static LogRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  LogLevel get level => $_getN(0);\n  @$pb.TagNumber(1)\n  set level(LogLevel v) { setField(1, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasLevel() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearLevel() => clearField(1);\n}\n\nclass StopRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'StopRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hcore'), createEmptyInstance: create)\n    ..hasRequiredFields = false\n  ;\n\n  StopRequest._() : super();\n  factory StopRequest() => create();\n  factory StopRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory StopRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  StopRequest clone() => StopRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  StopRequest copyWith(void Function(StopRequest) updates) => super.copyWith((message) => updates(message as StopRequest)) as StopRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static StopRequest create() => StopRequest._();\n  StopRequest createEmptyInstance() => create();\n  static $pb.PbList<StopRequest> createRepeated() => $pb.PbList<StopRequest>();\n  @$core.pragma('dart2js:noInline')\n  static StopRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<StopRequest>(create);\n  static StopRequest? _defaultInstance;\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/hcore.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/hcore.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n// ignore_for_file: UNDEFINED_SHOWN_NAME\nimport 'dart:core' as $core;\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nclass CoreStates extends $pb.ProtobufEnum {\n  static const CoreStates STOPPED = CoreStates._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'STOPPED');\n  static const CoreStates STARTING = CoreStates._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'STARTING');\n  static const CoreStates STARTED = CoreStates._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'STARTED');\n  static const CoreStates STOPPING = CoreStates._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'STOPPING');\n\n  static const $core.List<CoreStates> values = <CoreStates> [\n    STOPPED,\n    STARTING,\n    STARTED,\n    STOPPING,\n  ];\n\n  static final $core.Map<$core.int, CoreStates> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static CoreStates? valueOf($core.int value) => _byValue[value];\n\n  const CoreStates._($core.int v, $core.String n) : super(v, n);\n}\n\nclass MessageType extends $pb.ProtobufEnum {\n  static const MessageType EMPTY = MessageType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EMPTY');\n  static const MessageType EMPTY_CONFIGURATION = MessageType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EMPTY_CONFIGURATION');\n  static const MessageType START_COMMAND_SERVER = MessageType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'START_COMMAND_SERVER');\n  static const MessageType CREATE_SERVICE = MessageType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CREATE_SERVICE');\n  static const MessageType START_SERVICE = MessageType._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'START_SERVICE');\n  static const MessageType UNEXPECTED_ERROR = MessageType._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UNEXPECTED_ERROR');\n  static const MessageType ALREADY_STARTED = MessageType._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ALREADY_STARTED');\n  static const MessageType ALREADY_STOPPED = MessageType._(7, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ALREADY_STOPPED');\n  static const MessageType INSTANCE_NOT_FOUND = MessageType._(8, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'INSTANCE_NOT_FOUND');\n  static const MessageType INSTANCE_NOT_STOPPED = MessageType._(9, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'INSTANCE_NOT_STOPPED');\n  static const MessageType INSTANCE_NOT_STARTED = MessageType._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'INSTANCE_NOT_STARTED');\n  static const MessageType ERROR_BUILDING_CONFIG = MessageType._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ERROR_BUILDING_CONFIG');\n  static const MessageType ERROR_PARSING_CONFIG = MessageType._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ERROR_PARSING_CONFIG');\n  static const MessageType ERROR_READING_CONFIG = MessageType._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ERROR_READING_CONFIG');\n  static const MessageType ERROR_EXTENSION = MessageType._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ERROR_EXTENSION');\n\n  static const $core.List<MessageType> values = <MessageType> [\n    EMPTY,\n    EMPTY_CONFIGURATION,\n    START_COMMAND_SERVER,\n    CREATE_SERVICE,\n    START_SERVICE,\n    UNEXPECTED_ERROR,\n    ALREADY_STARTED,\n    ALREADY_STOPPED,\n    INSTANCE_NOT_FOUND,\n    INSTANCE_NOT_STOPPED,\n    INSTANCE_NOT_STARTED,\n    ERROR_BUILDING_CONFIG,\n    ERROR_PARSING_CONFIG,\n    ERROR_READING_CONFIG,\n    ERROR_EXTENSION,\n  ];\n\n  static final $core.Map<$core.int, MessageType> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static MessageType? valueOf($core.int value) => _byValue[value];\n\n  const MessageType._($core.int v, $core.String n) : super(v, n);\n}\n\nclass SetupMode extends $pb.ProtobufEnum {\n  static const SetupMode OLD = SetupMode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'OLD');\n  static const SetupMode GRPC_NORMAL = SetupMode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GRPC_NORMAL');\n  static const SetupMode GRPC_BACKGROUND = SetupMode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GRPC_BACKGROUND');\n  static const SetupMode GRPC_NORMAL_INSECURE = SetupMode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GRPC_NORMAL_INSECURE');\n  static const SetupMode GRPC_BACKGROUND_INSECURE = SetupMode._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GRPC_BACKGROUND_INSECURE');\n\n  static const $core.List<SetupMode> values = <SetupMode> [\n    OLD,\n    GRPC_NORMAL,\n    GRPC_BACKGROUND,\n    GRPC_NORMAL_INSECURE,\n    GRPC_BACKGROUND_INSECURE,\n  ];\n\n  static final $core.Map<$core.int, SetupMode> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static SetupMode? valueOf($core.int value) => _byValue[value];\n\n  const SetupMode._($core.int v, $core.String n) : super(v, n);\n}\n\nclass LogLevel extends $pb.ProtobufEnum {\n  static const LogLevel TRACE = LogLevel._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TRACE');\n  static const LogLevel DEBUG = LogLevel._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DEBUG');\n  static const LogLevel INFO = LogLevel._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'INFO');\n  static const LogLevel WARNING = LogLevel._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WARNING');\n  static const LogLevel ERROR = LogLevel._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ERROR');\n  static const LogLevel FATAL = LogLevel._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FATAL');\n\n  static const $core.List<LogLevel> values = <LogLevel> [\n    TRACE,\n    DEBUG,\n    INFO,\n    WARNING,\n    ERROR,\n    FATAL,\n  ];\n\n  static final $core.Map<$core.int, LogLevel> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static LogLevel? valueOf($core.int value) => _byValue[value];\n\n  const LogLevel._($core.int v, $core.String n) : super(v, n);\n}\n\nclass LogType extends $pb.ProtobufEnum {\n  static const LogType CORE = LogType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CORE');\n  static const LogType SERVICE = LogType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SERVICE');\n  static const LogType CONFIG = LogType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CONFIG');\n\n  static const $core.List<LogType> values = <LogType> [\n    CORE,\n    SERVICE,\n    CONFIG,\n  ];\n\n  static final $core.Map<$core.int, LogType> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static LogType? valueOf($core.int value) => _byValue[value];\n\n  const LogType._($core.int v, $core.String n) : super(v, n);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/hcore.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/hcore.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n@$core.Deprecated('Use coreStatesDescriptor instead')\nconst CoreStates$json = const {\n  '1': 'CoreStates',\n  '2': const [\n    const {'1': 'STOPPED', '2': 0},\n    const {'1': 'STARTING', '2': 1},\n    const {'1': 'STARTED', '2': 2},\n    const {'1': 'STOPPING', '2': 3},\n  ],\n};\n\n/// Descriptor for `CoreStates`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List coreStatesDescriptor = $convert.base64Decode('CgpDb3JlU3RhdGVzEgsKB1NUT1BQRUQQABIMCghTVEFSVElORxABEgsKB1NUQVJURUQQAhIMCghTVE9QUElORxAD');\n@$core.Deprecated('Use messageTypeDescriptor instead')\nconst MessageType$json = const {\n  '1': 'MessageType',\n  '2': const [\n    const {'1': 'EMPTY', '2': 0},\n    const {'1': 'EMPTY_CONFIGURATION', '2': 1},\n    const {'1': 'START_COMMAND_SERVER', '2': 2},\n    const {'1': 'CREATE_SERVICE', '2': 3},\n    const {'1': 'START_SERVICE', '2': 4},\n    const {'1': 'UNEXPECTED_ERROR', '2': 5},\n    const {'1': 'ALREADY_STARTED', '2': 6},\n    const {'1': 'ALREADY_STOPPED', '2': 7},\n    const {'1': 'INSTANCE_NOT_FOUND', '2': 8},\n    const {'1': 'INSTANCE_NOT_STOPPED', '2': 9},\n    const {'1': 'INSTANCE_NOT_STARTED', '2': 10},\n    const {'1': 'ERROR_BUILDING_CONFIG', '2': 11},\n    const {'1': 'ERROR_PARSING_CONFIG', '2': 12},\n    const {'1': 'ERROR_READING_CONFIG', '2': 13},\n    const {'1': 'ERROR_EXTENSION', '2': 14},\n  ],\n};\n\n/// Descriptor for `MessageType`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List messageTypeDescriptor = $convert.base64Decode('CgtNZXNzYWdlVHlwZRIJCgVFTVBUWRAAEhcKE0VNUFRZX0NPTkZJR1VSQVRJT04QARIYChRTVEFSVF9DT01NQU5EX1NFUlZFUhACEhIKDkNSRUFURV9TRVJWSUNFEAMSEQoNU1RBUlRfU0VSVklDRRAEEhQKEFVORVhQRUNURURfRVJST1IQBRITCg9BTFJFQURZX1NUQVJURUQQBhITCg9BTFJFQURZX1NUT1BQRUQQBxIWChJJTlNUQU5DRV9OT1RfRk9VTkQQCBIYChRJTlNUQU5DRV9OT1RfU1RPUFBFRBAJEhgKFElOU1RBTkNFX05PVF9TVEFSVEVEEAoSGQoVRVJST1JfQlVJTERJTkdfQ09ORklHEAsSGAoURVJST1JfUEFSU0lOR19DT05GSUcQDBIYChRFUlJPUl9SRUFESU5HX0NPTkZJRxANEhMKD0VSUk9SX0VYVEVOU0lPThAO');\n@$core.Deprecated('Use setupModeDescriptor instead')\nconst SetupMode$json = const {\n  '1': 'SetupMode',\n  '2': const [\n    const {'1': 'OLD', '2': 0},\n    const {'1': 'GRPC_NORMAL', '2': 1},\n    const {'1': 'GRPC_BACKGROUND', '2': 2},\n    const {'1': 'GRPC_NORMAL_INSECURE', '2': 3},\n    const {'1': 'GRPC_BACKGROUND_INSECURE', '2': 4},\n  ],\n};\n\n/// Descriptor for `SetupMode`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List setupModeDescriptor = $convert.base64Decode('CglTZXR1cE1vZGUSBwoDT0xEEAASDwoLR1JQQ19OT1JNQUwQARITCg9HUlBDX0JBQ0tHUk9VTkQQAhIYChRHUlBDX05PUk1BTF9JTlNFQ1VSRRADEhwKGEdSUENfQkFDS0dST1VORF9JTlNFQ1VSRRAE');\n@$core.Deprecated('Use logLevelDescriptor instead')\nconst LogLevel$json = const {\n  '1': 'LogLevel',\n  '2': const [\n    const {'1': 'TRACE', '2': 0},\n    const {'1': 'DEBUG', '2': 1},\n    const {'1': 'INFO', '2': 2},\n    const {'1': 'WARNING', '2': 3},\n    const {'1': 'ERROR', '2': 4},\n    const {'1': 'FATAL', '2': 5},\n  ],\n};\n\n/// Descriptor for `LogLevel`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List logLevelDescriptor = $convert.base64Decode('CghMb2dMZXZlbBIJCgVUUkFDRRAAEgkKBURFQlVHEAESCAoESU5GTxACEgsKB1dBUk5JTkcQAxIJCgVFUlJPUhAEEgkKBUZBVEFMEAU=');\n@$core.Deprecated('Use logTypeDescriptor instead')\nconst LogType$json = const {\n  '1': 'LogType',\n  '2': const [\n    const {'1': 'CORE', '2': 0},\n    const {'1': 'SERVICE', '2': 1},\n    const {'1': 'CONFIG', '2': 2},\n  ],\n};\n\n/// Descriptor for `LogType`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List logTypeDescriptor = $convert.base64Decode('CgdMb2dUeXBlEggKBENPUkUQABILCgdTRVJWSUNFEAESCgoGQ09ORklHEAI=');\n@$core.Deprecated('Use coreInfoResponseDescriptor instead')\nconst CoreInfoResponse$json = const {\n  '1': 'CoreInfoResponse',\n  '2': const [\n    const {'1': 'core_state', '3': 1, '4': 1, '5': 14, '6': '.hcore.CoreStates', '10': 'coreState'},\n    const {'1': 'message_type', '3': 2, '4': 1, '5': 14, '6': '.hcore.MessageType', '10': 'messageType'},\n    const {'1': 'message', '3': 3, '4': 1, '5': 9, '10': 'message'},\n  ],\n};\n\n/// Descriptor for `CoreInfoResponse`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List coreInfoResponseDescriptor = $convert.base64Decode('ChBDb3JlSW5mb1Jlc3BvbnNlEjAKCmNvcmVfc3RhdGUYASABKA4yES5oY29yZS5Db3JlU3RhdGVzUgljb3JlU3RhdGUSNQoMbWVzc2FnZV90eXBlGAIgASgOMhIuaGNvcmUuTWVzc2FnZVR5cGVSC21lc3NhZ2VUeXBlEhgKB21lc3NhZ2UYAyABKAlSB21lc3NhZ2U=');\n@$core.Deprecated('Use startRequestDescriptor instead')\nconst StartRequest$json = const {\n  '1': 'StartRequest',\n  '2': const [\n    const {'1': 'config_path', '3': 1, '4': 1, '5': 9, '10': 'configPath'},\n    const {'1': 'config_content', '3': 2, '4': 1, '5': 9, '10': 'configContent'},\n    const {'1': 'disable_memory_limit', '3': 3, '4': 1, '5': 8, '10': 'disableMemoryLimit'},\n    const {'1': 'delay_start', '3': 4, '4': 1, '5': 8, '10': 'delayStart'},\n    const {'1': 'enable_old_command_server', '3': 5, '4': 1, '5': 8, '10': 'enableOldCommandServer'},\n    const {'1': 'enable_raw_config', '3': 6, '4': 1, '5': 8, '10': 'enableRawConfig'},\n    const {'1': 'config_name', '3': 7, '4': 1, '5': 9, '10': 'configName'},\n  ],\n};\n\n/// Descriptor for `StartRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List startRequestDescriptor = $convert.base64Decode('CgxTdGFydFJlcXVlc3QSHwoLY29uZmlnX3BhdGgYASABKAlSCmNvbmZpZ1BhdGgSJQoOY29uZmlnX2NvbnRlbnQYAiABKAlSDWNvbmZpZ0NvbnRlbnQSMAoUZGlzYWJsZV9tZW1vcnlfbGltaXQYAyABKAhSEmRpc2FibGVNZW1vcnlMaW1pdBIfCgtkZWxheV9zdGFydBgEIAEoCFIKZGVsYXlTdGFydBI5ChllbmFibGVfb2xkX2NvbW1hbmRfc2VydmVyGAUgASgIUhZlbmFibGVPbGRDb21tYW5kU2VydmVyEioKEWVuYWJsZV9yYXdfY29uZmlnGAYgASgIUg9lbmFibGVSYXdDb25maWcSHwoLY29uZmlnX25hbWUYByABKAlSCmNvbmZpZ05hbWU=');\n@$core.Deprecated('Use closeRequestDescriptor instead')\nconst CloseRequest$json = const {\n  '1': 'CloseRequest',\n  '2': const [\n    const {'1': 'mode', '3': 1, '4': 1, '5': 14, '6': '.hcore.SetupMode', '10': 'mode'},\n  ],\n};\n\n/// Descriptor for `CloseRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List closeRequestDescriptor = $convert.base64Decode('CgxDbG9zZVJlcXVlc3QSJAoEbW9kZRgBIAEoDjIQLmhjb3JlLlNldHVwTW9kZVIEbW9kZQ==');\n@$core.Deprecated('Use setupRequestDescriptor instead')\nconst SetupRequest$json = const {\n  '1': 'SetupRequest',\n  '2': const [\n    const {'1': 'base_path', '3': 1, '4': 1, '5': 9, '10': 'basePath'},\n    const {'1': 'working_dir', '3': 2, '4': 1, '5': 9, '10': 'workingDir'},\n    const {'1': 'temp_dir', '3': 3, '4': 1, '5': 9, '10': 'tempDir'},\n    const {'1': 'flutter_status_port', '3': 4, '4': 1, '5': 3, '10': 'flutterStatusPort'},\n    const {'1': 'listen', '3': 5, '4': 1, '5': 9, '10': 'listen'},\n    const {'1': 'secret', '3': 6, '4': 1, '5': 9, '10': 'secret'},\n    const {'1': 'debug', '3': 7, '4': 1, '5': 8, '10': 'debug'},\n    const {'1': 'mode', '3': 8, '4': 1, '5': 14, '6': '.hcore.SetupMode', '10': 'mode'},\n    const {'1': 'fix_android_stack', '3': 9, '4': 1, '5': 8, '10': 'fixAndroidStack'},\n  ],\n};\n\n/// Descriptor for `SetupRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List setupRequestDescriptor = $convert.base64Decode('CgxTZXR1cFJlcXVlc3QSGwoJYmFzZV9wYXRoGAEgASgJUghiYXNlUGF0aBIfCgt3b3JraW5nX2RpchgCIAEoCVIKd29ya2luZ0RpchIZCgh0ZW1wX2RpchgDIAEoCVIHdGVtcERpchIuChNmbHV0dGVyX3N0YXR1c19wb3J0GAQgASgDUhFmbHV0dGVyU3RhdHVzUG9ydBIWCgZsaXN0ZW4YBSABKAlSBmxpc3RlbhIWCgZzZWNyZXQYBiABKAlSBnNlY3JldBIUCgVkZWJ1ZxgHIAEoCFIFZGVidWcSJAoEbW9kZRgIIAEoDjIQLmhjb3JlLlNldHVwTW9kZVIEbW9kZRIqChFmaXhfYW5kcm9pZF9zdGFjaxgJIAEoCFIPZml4QW5kcm9pZFN0YWNr');\n@$core.Deprecated('Use systemInfoDescriptor instead')\nconst SystemInfo$json = const {\n  '1': 'SystemInfo',\n  '2': const [\n    const {'1': 'memory', '3': 1, '4': 1, '5': 3, '10': 'memory'},\n    const {'1': 'goroutines', '3': 2, '4': 1, '5': 5, '10': 'goroutines'},\n    const {'1': 'connections_in', '3': 3, '4': 1, '5': 5, '10': 'connectionsIn'},\n    const {'1': 'connections_out', '3': 4, '4': 1, '5': 5, '10': 'connectionsOut'},\n    const {'1': 'traffic_available', '3': 5, '4': 1, '5': 8, '10': 'trafficAvailable'},\n    const {'1': 'uplink', '3': 6, '4': 1, '5': 3, '10': 'uplink'},\n    const {'1': 'downlink', '3': 7, '4': 1, '5': 3, '10': 'downlink'},\n    const {'1': 'uplink_total', '3': 8, '4': 1, '5': 3, '10': 'uplinkTotal'},\n    const {'1': 'downlink_total', '3': 9, '4': 1, '5': 3, '10': 'downlinkTotal'},\n    const {'1': 'current_outbound', '3': 10, '4': 1, '5': 9, '10': 'currentOutbound'},\n    const {'1': 'current_profile', '3': 11, '4': 1, '5': 9, '10': 'currentProfile'},\n  ],\n};\n\n/// Descriptor for `SystemInfo`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List systemInfoDescriptor = $convert.base64Decode('CgpTeXN0ZW1JbmZvEhYKBm1lbW9yeRgBIAEoA1IGbWVtb3J5Eh4KCmdvcm91dGluZXMYAiABKAVSCmdvcm91dGluZXMSJQoOY29ubmVjdGlvbnNfaW4YAyABKAVSDWNvbm5lY3Rpb25zSW4SJwoPY29ubmVjdGlvbnNfb3V0GAQgASgFUg5jb25uZWN0aW9uc091dBIrChF0cmFmZmljX2F2YWlsYWJsZRgFIAEoCFIQdHJhZmZpY0F2YWlsYWJsZRIWCgZ1cGxpbmsYBiABKANSBnVwbGluaxIaCghkb3dubGluaxgHIAEoA1IIZG93bmxpbmsSIQoMdXBsaW5rX3RvdGFsGAggASgDUgt1cGxpbmtUb3RhbBIlCg5kb3dubGlua190b3RhbBgJIAEoA1INZG93bmxpbmtUb3RhbBIpChBjdXJyZW50X291dGJvdW5kGAogASgJUg9jdXJyZW50T3V0Ym91bmQSJwoPY3VycmVudF9wcm9maWxlGAsgASgJUg5jdXJyZW50UHJvZmlsZQ==');\n@$core.Deprecated('Use outboundInfoDescriptor instead')\nconst OutboundInfo$json = const {\n  '1': 'OutboundInfo',\n  '2': const [\n    const {'1': 'tag', '3': 1, '4': 1, '5': 9, '10': 'tag'},\n    const {'1': 'type', '3': 2, '4': 1, '5': 9, '10': 'type'},\n    const {'1': 'url_test_time', '3': 3, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'urlTestTime'},\n    const {'1': 'url_test_delay', '3': 4, '4': 1, '5': 5, '10': 'urlTestDelay'},\n    const {'1': 'ipinfo', '3': 5, '4': 1, '5': 11, '6': '.hcore.IpInfo', '9': 0, '10': 'ipinfo', '17': true},\n    const {'1': 'is_selected', '3': 6, '4': 1, '5': 8, '10': 'isSelected'},\n    const {'1': 'is_group', '3': 7, '4': 1, '5': 8, '10': 'isGroup'},\n    const {'1': 'group_selected_tag', '3': 13, '4': 1, '5': 9, '9': 1, '10': 'groupSelectedTag', '17': true},\n    const {'1': 'group_selected_tag_display', '3': 14, '4': 1, '5': 9, '9': 2, '10': 'groupSelectedTagDisplay', '17': true},\n    const {'1': 'is_secure', '3': 8, '4': 1, '5': 8, '10': 'isSecure'},\n    const {'1': 'is_visible', '3': 9, '4': 1, '5': 8, '10': 'isVisible'},\n    const {'1': 'port', '3': 10, '4': 1, '5': 13, '10': 'port'},\n    const {'1': 'host', '3': 11, '4': 1, '5': 9, '10': 'host'},\n    const {'1': 'tag_display', '3': 12, '4': 1, '5': 9, '10': 'tagDisplay'},\n    const {'1': 'upload', '3': 15, '4': 1, '5': 3, '10': 'upload'},\n    const {'1': 'download', '3': 16, '4': 1, '5': 3, '10': 'download'},\n  ],\n  '8': const [\n    const {'1': '_ipinfo'},\n    const {'1': '_group_selected_tag'},\n    const {'1': '_group_selected_tag_display'},\n  ],\n};\n\n/// Descriptor for `OutboundInfo`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List outboundInfoDescriptor = $convert.base64Decode('CgxPdXRib3VuZEluZm8SEAoDdGFnGAEgASgJUgN0YWcSEgoEdHlwZRgCIAEoCVIEdHlwZRI+Cg11cmxfdGVzdF90aW1lGAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcFILdXJsVGVzdFRpbWUSJAoOdXJsX3Rlc3RfZGVsYXkYBCABKAVSDHVybFRlc3REZWxheRIqCgZpcGluZm8YBSABKAsyDS5oY29yZS5JcEluZm9IAFIGaXBpbmZviAEBEh8KC2lzX3NlbGVjdGVkGAYgASgIUgppc1NlbGVjdGVkEhkKCGlzX2dyb3VwGAcgASgIUgdpc0dyb3VwEjEKEmdyb3VwX3NlbGVjdGVkX3RhZxgNIAEoCUgBUhBncm91cFNlbGVjdGVkVGFniAEBEkAKGmdyb3VwX3NlbGVjdGVkX3RhZ19kaXNwbGF5GA4gASgJSAJSF2dyb3VwU2VsZWN0ZWRUYWdEaXNwbGF5iAEBEhsKCWlzX3NlY3VyZRgIIAEoCFIIaXNTZWN1cmUSHQoKaXNfdmlzaWJsZRgJIAEoCFIJaXNWaXNpYmxlEhIKBHBvcnQYCiABKA1SBHBvcnQSEgoEaG9zdBgLIAEoCVIEaG9zdBIfCgt0YWdfZGlzcGxheRgMIAEoCVIKdGFnRGlzcGxheRIWCgZ1cGxvYWQYDyABKANSBnVwbG9hZBIaCghkb3dubG9hZBgQIAEoA1IIZG93bmxvYWRCCQoHX2lwaW5mb0IVChNfZ3JvdXBfc2VsZWN0ZWRfdGFnQh0KG19ncm91cF9zZWxlY3RlZF90YWdfZGlzcGxheQ==');\n@$core.Deprecated('Use ipInfoDescriptor instead')\nconst IpInfo$json = const {\n  '1': 'IpInfo',\n  '2': const [\n    const {'1': 'ip', '3': 1, '4': 1, '5': 9, '10': 'ip'},\n    const {'1': 'country_code', '3': 2, '4': 1, '5': 9, '10': 'country_code'},\n    const {'1': 'region', '3': 3, '4': 1, '5': 9, '10': 'region'},\n    const {'1': 'city', '3': 4, '4': 1, '5': 9, '10': 'city'},\n    const {'1': 'asn', '3': 5, '4': 1, '5': 5, '10': 'asn'},\n    const {'1': 'org', '3': 6, '4': 1, '5': 9, '10': 'org'},\n    const {'1': 'latitude', '3': 7, '4': 1, '5': 1, '10': 'latitude'},\n    const {'1': 'longitude', '3': 8, '4': 1, '5': 1, '10': 'longitude'},\n    const {'1': 'postal_code', '3': 9, '4': 1, '5': 9, '10': 'postal_code'},\n  ],\n};\n\n/// Descriptor for `IpInfo`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List ipInfoDescriptor = $convert.base64Decode('CgZJcEluZm8SDgoCaXAYASABKAlSAmlwEiIKDGNvdW50cnlfY29kZRgCIAEoCVIMY291bnRyeV9jb2RlEhYKBnJlZ2lvbhgDIAEoCVIGcmVnaW9uEhIKBGNpdHkYBCABKAlSBGNpdHkSEAoDYXNuGAUgASgFUgNhc24SEAoDb3JnGAYgASgJUgNvcmcSGgoIbGF0aXR1ZGUYByABKAFSCGxhdGl0dWRlEhwKCWxvbmdpdHVkZRgIIAEoAVIJbG9uZ2l0dWRlEiAKC3Bvc3RhbF9jb2RlGAkgASgJUgtwb3N0YWxfY29kZQ==');\n@$core.Deprecated('Use outboundGroupDescriptor instead')\nconst OutboundGroup$json = const {\n  '1': 'OutboundGroup',\n  '2': const [\n    const {'1': 'tag', '3': 1, '4': 1, '5': 9, '10': 'tag'},\n    const {'1': 'type', '3': 2, '4': 1, '5': 9, '10': 'type'},\n    const {'1': 'selected', '3': 3, '4': 1, '5': 9, '10': 'selected'},\n    const {'1': 'selectable', '3': 4, '4': 1, '5': 8, '10': 'selectable'},\n    const {'1': 'Is_expand', '3': 5, '4': 1, '5': 8, '10': 'IsExpand'},\n    const {'1': 'items', '3': 6, '4': 3, '5': 11, '6': '.hcore.OutboundInfo', '10': 'items'},\n  ],\n};\n\n/// Descriptor for `OutboundGroup`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List outboundGroupDescriptor = $convert.base64Decode('Cg1PdXRib3VuZEdyb3VwEhAKA3RhZxgBIAEoCVIDdGFnEhIKBHR5cGUYAiABKAlSBHR5cGUSGgoIc2VsZWN0ZWQYAyABKAlSCHNlbGVjdGVkEh4KCnNlbGVjdGFibGUYBCABKAhSCnNlbGVjdGFibGUSGwoJSXNfZXhwYW5kGAUgASgIUghJc0V4cGFuZBIpCgVpdGVtcxgGIAMoCzITLmhjb3JlLk91dGJvdW5kSW5mb1IFaXRlbXM=');\n@$core.Deprecated('Use outboundGroupListDescriptor instead')\nconst OutboundGroupList$json = const {\n  '1': 'OutboundGroupList',\n  '2': const [\n    const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.hcore.OutboundGroup', '10': 'items'},\n  ],\n};\n\n/// Descriptor for `OutboundGroupList`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List outboundGroupListDescriptor = $convert.base64Decode('ChFPdXRib3VuZEdyb3VwTGlzdBIqCgVpdGVtcxgBIAMoCzIULmhjb3JlLk91dGJvdW5kR3JvdXBSBWl0ZW1z');\n@$core.Deprecated('Use warpAccountDescriptor instead')\nconst WarpAccount$json = const {\n  '1': 'WarpAccount',\n  '2': const [\n    const {'1': 'account_id', '3': 1, '4': 1, '5': 9, '10': 'accountId'},\n    const {'1': 'access_token', '3': 2, '4': 1, '5': 9, '10': 'accessToken'},\n  ],\n};\n\n/// Descriptor for `WarpAccount`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List warpAccountDescriptor = $convert.base64Decode('CgtXYXJwQWNjb3VudBIdCgphY2NvdW50X2lkGAEgASgJUglhY2NvdW50SWQSIQoMYWNjZXNzX3Rva2VuGAIgASgJUgthY2Nlc3NUb2tlbg==');\n@$core.Deprecated('Use warpWireguardConfigDescriptor instead')\nconst WarpWireguardConfig$json = const {\n  '1': 'WarpWireguardConfig',\n  '2': const [\n    const {'1': 'private_key', '3': 1, '4': 1, '5': 9, '10': 'private-key'},\n    const {'1': 'local_address_ipv4', '3': 2, '4': 1, '5': 9, '10': 'local-address-ipv4'},\n    const {'1': 'local_address_ipv6', '3': 3, '4': 1, '5': 9, '10': 'local-address-ipv6'},\n    const {'1': 'peer_public_key', '3': 4, '4': 1, '5': 9, '10': 'peer-public-key'},\n    const {'1': 'client_id', '3': 5, '4': 1, '5': 9, '10': 'client-id'},\n  ],\n};\n\n/// Descriptor for `WarpWireguardConfig`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List warpWireguardConfigDescriptor = $convert.base64Decode('ChNXYXJwV2lyZWd1YXJkQ29uZmlnEiAKC3ByaXZhdGVfa2V5GAEgASgJUgtwcml2YXRlLWtleRIuChJsb2NhbF9hZGRyZXNzX2lwdjQYAiABKAlSEmxvY2FsLWFkZHJlc3MtaXB2NBIuChJsb2NhbF9hZGRyZXNzX2lwdjYYAyABKAlSEmxvY2FsLWFkZHJlc3MtaXB2NhIoCg9wZWVyX3B1YmxpY19rZXkYBCABKAlSD3BlZXItcHVibGljLWtleRIcCgljbGllbnRfaWQYBSABKAlSCWNsaWVudC1pZA==');\n@$core.Deprecated('Use warpGenerationResponseDescriptor instead')\nconst WarpGenerationResponse$json = const {\n  '1': 'WarpGenerationResponse',\n  '2': const [\n    const {'1': 'account', '3': 1, '4': 1, '5': 11, '6': '.hcore.WarpAccount', '10': 'account'},\n    const {'1': 'log', '3': 2, '4': 1, '5': 9, '10': 'log'},\n    const {'1': 'config', '3': 3, '4': 1, '5': 11, '6': '.hcore.WarpWireguardConfig', '10': 'config'},\n  ],\n};\n\n/// Descriptor for `WarpGenerationResponse`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List warpGenerationResponseDescriptor = $convert.base64Decode('ChZXYXJwR2VuZXJhdGlvblJlc3BvbnNlEiwKB2FjY291bnQYASABKAsyEi5oY29yZS5XYXJwQWNjb3VudFIHYWNjb3VudBIQCgNsb2cYAiABKAlSA2xvZxIyCgZjb25maWcYAyABKAsyGi5oY29yZS5XYXJwV2lyZWd1YXJkQ29uZmlnUgZjb25maWc=');\n@$core.Deprecated('Use systemProxyStatusDescriptor instead')\nconst SystemProxyStatus$json = const {\n  '1': 'SystemProxyStatus',\n  '2': const [\n    const {'1': 'available', '3': 1, '4': 1, '5': 8, '10': 'available'},\n    const {'1': 'enabled', '3': 2, '4': 1, '5': 8, '10': 'enabled'},\n  ],\n};\n\n/// Descriptor for `SystemProxyStatus`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List systemProxyStatusDescriptor = $convert.base64Decode('ChFTeXN0ZW1Qcm94eVN0YXR1cxIcCglhdmFpbGFibGUYASABKAhSCWF2YWlsYWJsZRIYCgdlbmFibGVkGAIgASgIUgdlbmFibGVk');\n@$core.Deprecated('Use parseRequestDescriptor instead')\nconst ParseRequest$json = const {\n  '1': 'ParseRequest',\n  '2': const [\n    const {'1': 'content', '3': 1, '4': 1, '5': 9, '10': 'content'},\n    const {'1': 'config_path', '3': 2, '4': 1, '5': 9, '10': 'configPath'},\n    const {'1': 'temp_path', '3': 3, '4': 1, '5': 9, '10': 'tempPath'},\n    const {'1': 'debug', '3': 4, '4': 1, '5': 8, '10': 'debug'},\n  ],\n};\n\n/// Descriptor for `ParseRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List parseRequestDescriptor = $convert.base64Decode('CgxQYXJzZVJlcXVlc3QSGAoHY29udGVudBgBIAEoCVIHY29udGVudBIfCgtjb25maWdfcGF0aBgCIAEoCVIKY29uZmlnUGF0aBIbCgl0ZW1wX3BhdGgYAyABKAlSCHRlbXBQYXRoEhQKBWRlYnVnGAQgASgIUgVkZWJ1Zw==');\n@$core.Deprecated('Use parseResponseDescriptor instead')\nconst ParseResponse$json = const {\n  '1': 'ParseResponse',\n  '2': const [\n    const {'1': 'response_code', '3': 1, '4': 1, '5': 14, '6': '.hcommon.ResponseCode', '10': 'responseCode'},\n    const {'1': 'content', '3': 2, '4': 1, '5': 9, '10': 'content'},\n    const {'1': 'message', '3': 3, '4': 1, '5': 9, '10': 'message'},\n  ],\n};\n\n/// Descriptor for `ParseResponse`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List parseResponseDescriptor = $convert.base64Decode('Cg1QYXJzZVJlc3BvbnNlEjoKDXJlc3BvbnNlX2NvZGUYASABKA4yFS5oY29tbW9uLlJlc3BvbnNlQ29kZVIMcmVzcG9uc2VDb2RlEhgKB2NvbnRlbnQYAiABKAlSB2NvbnRlbnQSGAoHbWVzc2FnZRgDIAEoCVIHbWVzc2FnZQ==');\n@$core.Deprecated('Use changeHiddifySettingsRequestDescriptor instead')\nconst ChangeHiddifySettingsRequest$json = const {\n  '1': 'ChangeHiddifySettingsRequest',\n  '2': const [\n    const {'1': 'hiddify_settings_json', '3': 1, '4': 1, '5': 9, '10': 'hiddifySettingsJson'},\n  ],\n};\n\n/// Descriptor for `ChangeHiddifySettingsRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List changeHiddifySettingsRequestDescriptor = $convert.base64Decode('ChxDaGFuZ2VIaWRkaWZ5U2V0dGluZ3NSZXF1ZXN0EjIKFWhpZGRpZnlfc2V0dGluZ3NfanNvbhgBIAEoCVITaGlkZGlmeVNldHRpbmdzSnNvbg==');\n@$core.Deprecated('Use generateConfigRequestDescriptor instead')\nconst GenerateConfigRequest$json = const {\n  '1': 'GenerateConfigRequest',\n  '2': const [\n    const {'1': 'path', '3': 1, '4': 1, '5': 9, '10': 'path'},\n    const {'1': 'temp_path', '3': 2, '4': 1, '5': 9, '10': 'tempPath'},\n    const {'1': 'debug', '3': 3, '4': 1, '5': 8, '10': 'debug'},\n  ],\n};\n\n/// Descriptor for `GenerateConfigRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List generateConfigRequestDescriptor = $convert.base64Decode('ChVHZW5lcmF0ZUNvbmZpZ1JlcXVlc3QSEgoEcGF0aBgBIAEoCVIEcGF0aBIbCgl0ZW1wX3BhdGgYAiABKAlSCHRlbXBQYXRoEhQKBWRlYnVnGAMgASgIUgVkZWJ1Zw==');\n@$core.Deprecated('Use generateConfigResponseDescriptor instead')\nconst GenerateConfigResponse$json = const {\n  '1': 'GenerateConfigResponse',\n  '2': const [\n    const {'1': 'config_content', '3': 1, '4': 1, '5': 9, '10': 'configContent'},\n  ],\n};\n\n/// Descriptor for `GenerateConfigResponse`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List generateConfigResponseDescriptor = $convert.base64Decode('ChZHZW5lcmF0ZUNvbmZpZ1Jlc3BvbnNlEiUKDmNvbmZpZ19jb250ZW50GAEgASgJUg1jb25maWdDb250ZW50');\n@$core.Deprecated('Use selectOutboundRequestDescriptor instead')\nconst SelectOutboundRequest$json = const {\n  '1': 'SelectOutboundRequest',\n  '2': const [\n    const {'1': 'group_tag', '3': 1, '4': 1, '5': 9, '10': 'groupTag'},\n    const {'1': 'outbound_tag', '3': 2, '4': 1, '5': 9, '10': 'outboundTag'},\n  ],\n};\n\n/// Descriptor for `SelectOutboundRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List selectOutboundRequestDescriptor = $convert.base64Decode('ChVTZWxlY3RPdXRib3VuZFJlcXVlc3QSGwoJZ3JvdXBfdGFnGAEgASgJUghncm91cFRhZxIhCgxvdXRib3VuZF90YWcYAiABKAlSC291dGJvdW5kVGFn');\n@$core.Deprecated('Use urlTestRequestDescriptor instead')\nconst UrlTestRequest$json = const {\n  '1': 'UrlTestRequest',\n  '2': const [\n    const {'1': 'tag', '3': 1, '4': 1, '5': 9, '10': 'tag'},\n  ],\n};\n\n/// Descriptor for `UrlTestRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List urlTestRequestDescriptor = $convert.base64Decode('Cg5VcmxUZXN0UmVxdWVzdBIQCgN0YWcYASABKAlSA3RhZw==');\n@$core.Deprecated('Use generateWarpConfigRequestDescriptor instead')\nconst GenerateWarpConfigRequest$json = const {\n  '1': 'GenerateWarpConfigRequest',\n  '2': const [\n    const {'1': 'license_key', '3': 1, '4': 1, '5': 9, '10': 'licenseKey'},\n    const {'1': 'account_id', '3': 2, '4': 1, '5': 9, '10': 'accountId'},\n    const {'1': 'access_token', '3': 3, '4': 1, '5': 9, '10': 'accessToken'},\n  ],\n};\n\n/// Descriptor for `GenerateWarpConfigRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List generateWarpConfigRequestDescriptor = $convert.base64Decode('ChlHZW5lcmF0ZVdhcnBDb25maWdSZXF1ZXN0Eh8KC2xpY2Vuc2Vfa2V5GAEgASgJUgpsaWNlbnNlS2V5Eh0KCmFjY291bnRfaWQYAiABKAlSCWFjY291bnRJZBIhCgxhY2Nlc3NfdG9rZW4YAyABKAlSC2FjY2Vzc1Rva2Vu');\n@$core.Deprecated('Use setSystemProxyEnabledRequestDescriptor instead')\nconst SetSystemProxyEnabledRequest$json = const {\n  '1': 'SetSystemProxyEnabledRequest',\n  '2': const [\n    const {'1': 'is_enabled', '3': 1, '4': 1, '5': 8, '10': 'isEnabled'},\n  ],\n};\n\n/// Descriptor for `SetSystemProxyEnabledRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List setSystemProxyEnabledRequestDescriptor = $convert.base64Decode('ChxTZXRTeXN0ZW1Qcm94eUVuYWJsZWRSZXF1ZXN0Eh0KCmlzX2VuYWJsZWQYASABKAhSCWlzRW5hYmxlZA==');\n@$core.Deprecated('Use logMessageDescriptor instead')\nconst LogMessage$json = const {\n  '1': 'LogMessage',\n  '2': const [\n    const {'1': 'level', '3': 1, '4': 1, '5': 14, '6': '.hcore.LogLevel', '10': 'level'},\n    const {'1': 'type', '3': 2, '4': 1, '5': 14, '6': '.hcore.LogType', '10': 'type'},\n    const {'1': 'message', '3': 3, '4': 1, '5': 9, '10': 'message'},\n    const {'1': 'time', '3': 4, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'time'},\n  ],\n};\n\n/// Descriptor for `LogMessage`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List logMessageDescriptor = $convert.base64Decode('CgpMb2dNZXNzYWdlEiUKBWxldmVsGAEgASgOMg8uaGNvcmUuTG9nTGV2ZWxSBWxldmVsEiIKBHR5cGUYAiABKA4yDi5oY29yZS5Mb2dUeXBlUgR0eXBlEhgKB21lc3NhZ2UYAyABKAlSB21lc3NhZ2USLgoEdGltZRgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBSBHRpbWU=');\n@$core.Deprecated('Use logRequestDescriptor instead')\nconst LogRequest$json = const {\n  '1': 'LogRequest',\n  '2': const [\n    const {'1': 'level', '3': 1, '4': 1, '5': 14, '6': '.hcore.LogLevel', '10': 'level'},\n  ],\n};\n\n/// Descriptor for `LogRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List logRequestDescriptor = $convert.base64Decode('CgpMb2dSZXF1ZXN0EiUKBWxldmVsGAEgASgOMg8uaGNvcmUuTG9nTGV2ZWxSBWxldmVs');\n@$core.Deprecated('Use stopRequestDescriptor instead')\nconst StopRequest$json = const {\n  '1': 'StopRequest',\n};\n\n/// Descriptor for `StopRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List stopRequestDescriptor = $convert.base64Decode('CgtTdG9wUmVxdWVzdA==');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/hcore_service.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/hcore_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/hcore_service.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/hcore_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/hcore_service.pbgrpc.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/hcore_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:async' as $async;\n\nimport 'dart:core' as $core;\n\nimport 'package:grpc/service_api.dart' as $grpc;\nimport 'hcore.pb.dart' as $0;\nimport '../hcommon/common.pb.dart' as $1;\nexport 'hcore_service.pb.dart';\n\nclass CoreClient extends $grpc.Client {\n  static final _$start =\n      $grpc.ClientMethod<$0.StartRequest, $0.CoreInfoResponse>(\n          '/hcore.Core/Start',\n          ($0.StartRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $0.CoreInfoResponse.fromBuffer(value));\n  static final _$coreInfoListener =\n      $grpc.ClientMethod<$1.Empty, $0.CoreInfoResponse>(\n          '/hcore.Core/CoreInfoListener',\n          ($1.Empty value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $0.CoreInfoResponse.fromBuffer(value));\n  static final _$outboundsInfo =\n      $grpc.ClientMethod<$1.Empty, $0.OutboundGroupList>(\n          '/hcore.Core/OutboundsInfo',\n          ($1.Empty value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $0.OutboundGroupList.fromBuffer(value));\n  static final _$mainOutboundsInfo =\n      $grpc.ClientMethod<$1.Empty, $0.OutboundGroupList>(\n          '/hcore.Core/MainOutboundsInfo',\n          ($1.Empty value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $0.OutboundGroupList.fromBuffer(value));\n  static final _$getSystemInfo = $grpc.ClientMethod<$1.Empty, $0.SystemInfo>(\n      '/hcore.Core/GetSystemInfo',\n      ($1.Empty value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $0.SystemInfo.fromBuffer(value));\n  static final _$getSystemInfoStream =\n      $grpc.ClientMethod<$1.Empty, $0.SystemInfo>(\n          '/hcore.Core/GetSystemInfoStream',\n          ($1.Empty value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) => $0.SystemInfo.fromBuffer(value));\n  static final _$setup = $grpc.ClientMethod<$0.SetupRequest, $1.Response>(\n      '/hcore.Core/Setup',\n      ($0.SetupRequest value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $1.Response.fromBuffer(value));\n  static final _$parse = $grpc.ClientMethod<$0.ParseRequest, $0.ParseResponse>(\n      '/hcore.Core/Parse',\n      ($0.ParseRequest value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $0.ParseResponse.fromBuffer(value));\n  static final _$changeHiddifySettings =\n      $grpc.ClientMethod<$0.ChangeHiddifySettingsRequest, $0.CoreInfoResponse>(\n          '/hcore.Core/ChangeHiddifySettings',\n          ($0.ChangeHiddifySettingsRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $0.CoreInfoResponse.fromBuffer(value));\n  static final _$startService =\n      $grpc.ClientMethod<$0.StartRequest, $0.CoreInfoResponse>(\n          '/hcore.Core/StartService',\n          ($0.StartRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $0.CoreInfoResponse.fromBuffer(value));\n  static final _$stop = $grpc.ClientMethod<$1.Empty, $0.CoreInfoResponse>(\n      '/hcore.Core/Stop',\n      ($1.Empty value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $0.CoreInfoResponse.fromBuffer(value));\n  static final _$restart =\n      $grpc.ClientMethod<$0.StartRequest, $0.CoreInfoResponse>(\n          '/hcore.Core/Restart',\n          ($0.StartRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $0.CoreInfoResponse.fromBuffer(value));\n  static final _$selectOutbound =\n      $grpc.ClientMethod<$0.SelectOutboundRequest, $1.Response>(\n          '/hcore.Core/SelectOutbound',\n          ($0.SelectOutboundRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) => $1.Response.fromBuffer(value));\n  static final _$urlTest = $grpc.ClientMethod<$0.UrlTestRequest, $1.Response>(\n      '/hcore.Core/UrlTest',\n      ($0.UrlTestRequest value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $1.Response.fromBuffer(value));\n  static final _$urlTestActive = $grpc.ClientMethod<$1.Empty, $1.Response>(\n      '/hcore.Core/UrlTestActive',\n      ($1.Empty value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $1.Response.fromBuffer(value));\n  static final _$generateWarpConfig = $grpc.ClientMethod<\n          $0.GenerateWarpConfigRequest, $0.WarpGenerationResponse>(\n      '/hcore.Core/GenerateWarpConfig',\n      ($0.GenerateWarpConfigRequest value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) =>\n          $0.WarpGenerationResponse.fromBuffer(value));\n  static final _$getSystemProxyStatus =\n      $grpc.ClientMethod<$1.Empty, $0.SystemProxyStatus>(\n          '/hcore.Core/GetSystemProxyStatus',\n          ($1.Empty value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $0.SystemProxyStatus.fromBuffer(value));\n  static final _$setSystemProxyEnabled =\n      $grpc.ClientMethod<$0.SetSystemProxyEnabledRequest, $1.Response>(\n          '/hcore.Core/SetSystemProxyEnabled',\n          ($0.SetSystemProxyEnabledRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) => $1.Response.fromBuffer(value));\n  static final _$logListener = $grpc.ClientMethod<$0.LogRequest, $0.LogMessage>(\n      '/hcore.Core/LogListener',\n      ($0.LogRequest value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $0.LogMessage.fromBuffer(value));\n  static final _$close = $grpc.ClientMethod<$0.CloseRequest, $1.Empty>(\n      '/hcore.Core/Close',\n      ($0.CloseRequest value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $1.Empty.fromBuffer(value));\n\n  CoreClient($grpc.ClientChannel channel,\n      {$grpc.CallOptions? options,\n      $core.Iterable<$grpc.ClientInterceptor>? interceptors})\n      : super(channel, options: options, interceptors: interceptors);\n\n  $grpc.ResponseFuture<$0.CoreInfoResponse> start($0.StartRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$start, request, options: options);\n  }\n\n  $grpc.ResponseStream<$0.CoreInfoResponse> coreInfoListener($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createStreamingCall(\n        _$coreInfoListener, $async.Stream.fromIterable([request]),\n        options: options);\n  }\n\n  $grpc.ResponseStream<$0.OutboundGroupList> outboundsInfo($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createStreamingCall(\n        _$outboundsInfo, $async.Stream.fromIterable([request]),\n        options: options);\n  }\n\n  $grpc.ResponseStream<$0.OutboundGroupList> mainOutboundsInfo($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createStreamingCall(\n        _$mainOutboundsInfo, $async.Stream.fromIterable([request]),\n        options: options);\n  }\n\n  $grpc.ResponseFuture<$0.SystemInfo> getSystemInfo($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$getSystemInfo, request, options: options);\n  }\n\n  $grpc.ResponseStream<$0.SystemInfo> getSystemInfoStream($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createStreamingCall(\n        _$getSystemInfoStream, $async.Stream.fromIterable([request]),\n        options: options);\n  }\n\n  $grpc.ResponseFuture<$1.Response> setup($0.SetupRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$setup, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$0.ParseResponse> parse($0.ParseRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$parse, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$0.CoreInfoResponse> changeHiddifySettings(\n      $0.ChangeHiddifySettingsRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$changeHiddifySettings, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$0.CoreInfoResponse> startService(\n      $0.StartRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$startService, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$0.CoreInfoResponse> stop($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$stop, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$0.CoreInfoResponse> restart($0.StartRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$restart, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$1.Response> selectOutbound(\n      $0.SelectOutboundRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$selectOutbound, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$1.Response> urlTest($0.UrlTestRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$urlTest, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$1.Response> urlTestActive($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$urlTestActive, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$0.WarpGenerationResponse> generateWarpConfig(\n      $0.GenerateWarpConfigRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$generateWarpConfig, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$0.SystemProxyStatus> getSystemProxyStatus(\n      $1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$getSystemProxyStatus, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$1.Response> setSystemProxyEnabled(\n      $0.SetSystemProxyEnabledRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$setSystemProxyEnabled, request, options: options);\n  }\n\n  $grpc.ResponseStream<$0.LogMessage> logListener($0.LogRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createStreamingCall(\n        _$logListener, $async.Stream.fromIterable([request]),\n        options: options);\n  }\n\n  $grpc.ResponseFuture<$1.Empty> close($0.CloseRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$close, request, options: options);\n  }\n}\n\nabstract class CoreServiceBase extends $grpc.Service {\n  $core.String get $name => 'hcore.Core';\n\n  CoreServiceBase() {\n    $addMethod($grpc.ServiceMethod<$0.StartRequest, $0.CoreInfoResponse>(\n        'Start',\n        start_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $0.StartRequest.fromBuffer(value),\n        ($0.CoreInfoResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $0.CoreInfoResponse>(\n        'CoreInfoListener',\n        coreInfoListener_Pre,\n        false,\n        true,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($0.CoreInfoResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $0.OutboundGroupList>(\n        'OutboundsInfo',\n        outboundsInfo_Pre,\n        false,\n        true,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($0.OutboundGroupList value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $0.OutboundGroupList>(\n        'MainOutboundsInfo',\n        mainOutboundsInfo_Pre,\n        false,\n        true,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($0.OutboundGroupList value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $0.SystemInfo>(\n        'GetSystemInfo',\n        getSystemInfo_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($0.SystemInfo value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $0.SystemInfo>(\n        'GetSystemInfoStream',\n        getSystemInfoStream_Pre,\n        false,\n        true,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($0.SystemInfo value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$0.SetupRequest, $1.Response>(\n        'Setup',\n        setup_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $0.SetupRequest.fromBuffer(value),\n        ($1.Response value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$0.ParseRequest, $0.ParseResponse>(\n        'Parse',\n        parse_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $0.ParseRequest.fromBuffer(value),\n        ($0.ParseResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$0.ChangeHiddifySettingsRequest,\n            $0.CoreInfoResponse>(\n        'ChangeHiddifySettings',\n        changeHiddifySettings_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) =>\n            $0.ChangeHiddifySettingsRequest.fromBuffer(value),\n        ($0.CoreInfoResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$0.StartRequest, $0.CoreInfoResponse>(\n        'StartService',\n        startService_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $0.StartRequest.fromBuffer(value),\n        ($0.CoreInfoResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $0.CoreInfoResponse>(\n        'Stop',\n        stop_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($0.CoreInfoResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$0.StartRequest, $0.CoreInfoResponse>(\n        'Restart',\n        restart_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $0.StartRequest.fromBuffer(value),\n        ($0.CoreInfoResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$0.SelectOutboundRequest, $1.Response>(\n        'SelectOutbound',\n        selectOutbound_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) =>\n            $0.SelectOutboundRequest.fromBuffer(value),\n        ($1.Response value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$0.UrlTestRequest, $1.Response>(\n        'UrlTest',\n        urlTest_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $0.UrlTestRequest.fromBuffer(value),\n        ($1.Response value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $1.Response>(\n        'UrlTestActive',\n        urlTestActive_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($1.Response value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$0.GenerateWarpConfigRequest,\n            $0.WarpGenerationResponse>(\n        'GenerateWarpConfig',\n        generateWarpConfig_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) =>\n            $0.GenerateWarpConfigRequest.fromBuffer(value),\n        ($0.WarpGenerationResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $0.SystemProxyStatus>(\n        'GetSystemProxyStatus',\n        getSystemProxyStatus_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($0.SystemProxyStatus value) => value.writeToBuffer()));\n    $addMethod(\n        $grpc.ServiceMethod<$0.SetSystemProxyEnabledRequest, $1.Response>(\n            'SetSystemProxyEnabled',\n            setSystemProxyEnabled_Pre,\n            false,\n            false,\n            ($core.List<$core.int> value) =>\n                $0.SetSystemProxyEnabledRequest.fromBuffer(value),\n            ($1.Response value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$0.LogRequest, $0.LogMessage>(\n        'LogListener',\n        logListener_Pre,\n        false,\n        true,\n        ($core.List<$core.int> value) => $0.LogRequest.fromBuffer(value),\n        ($0.LogMessage value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$0.CloseRequest, $1.Empty>(\n        'Close',\n        close_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $0.CloseRequest.fromBuffer(value),\n        ($1.Empty value) => value.writeToBuffer()));\n  }\n\n  $async.Future<$0.CoreInfoResponse> start_Pre(\n      $grpc.ServiceCall call, $async.Future<$0.StartRequest> request) async {\n    return start(call, await request);\n  }\n\n  $async.Stream<$0.CoreInfoResponse> coreInfoListener_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async* {\n    yield* coreInfoListener(call, await request);\n  }\n\n  $async.Stream<$0.OutboundGroupList> outboundsInfo_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async* {\n    yield* outboundsInfo(call, await request);\n  }\n\n  $async.Stream<$0.OutboundGroupList> mainOutboundsInfo_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async* {\n    yield* mainOutboundsInfo(call, await request);\n  }\n\n  $async.Future<$0.SystemInfo> getSystemInfo_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async {\n    return getSystemInfo(call, await request);\n  }\n\n  $async.Stream<$0.SystemInfo> getSystemInfoStream_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async* {\n    yield* getSystemInfoStream(call, await request);\n  }\n\n  $async.Future<$1.Response> setup_Pre(\n      $grpc.ServiceCall call, $async.Future<$0.SetupRequest> request) async {\n    return setup(call, await request);\n  }\n\n  $async.Future<$0.ParseResponse> parse_Pre(\n      $grpc.ServiceCall call, $async.Future<$0.ParseRequest> request) async {\n    return parse(call, await request);\n  }\n\n  $async.Future<$0.CoreInfoResponse> changeHiddifySettings_Pre(\n      $grpc.ServiceCall call,\n      $async.Future<$0.ChangeHiddifySettingsRequest> request) async {\n    return changeHiddifySettings(call, await request);\n  }\n\n  $async.Future<$0.CoreInfoResponse> startService_Pre(\n      $grpc.ServiceCall call, $async.Future<$0.StartRequest> request) async {\n    return startService(call, await request);\n  }\n\n  $async.Future<$0.CoreInfoResponse> stop_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async {\n    return stop(call, await request);\n  }\n\n  $async.Future<$0.CoreInfoResponse> restart_Pre(\n      $grpc.ServiceCall call, $async.Future<$0.StartRequest> request) async {\n    return restart(call, await request);\n  }\n\n  $async.Future<$1.Response> selectOutbound_Pre($grpc.ServiceCall call,\n      $async.Future<$0.SelectOutboundRequest> request) async {\n    return selectOutbound(call, await request);\n  }\n\n  $async.Future<$1.Response> urlTest_Pre(\n      $grpc.ServiceCall call, $async.Future<$0.UrlTestRequest> request) async {\n    return urlTest(call, await request);\n  }\n\n  $async.Future<$1.Response> urlTestActive_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async {\n    return urlTestActive(call, await request);\n  }\n\n  $async.Future<$0.WarpGenerationResponse> generateWarpConfig_Pre(\n      $grpc.ServiceCall call,\n      $async.Future<$0.GenerateWarpConfigRequest> request) async {\n    return generateWarpConfig(call, await request);\n  }\n\n  $async.Future<$0.SystemProxyStatus> getSystemProxyStatus_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async {\n    return getSystemProxyStatus(call, await request);\n  }\n\n  $async.Future<$1.Response> setSystemProxyEnabled_Pre($grpc.ServiceCall call,\n      $async.Future<$0.SetSystemProxyEnabledRequest> request) async {\n    return setSystemProxyEnabled(call, await request);\n  }\n\n  $async.Stream<$0.LogMessage> logListener_Pre(\n      $grpc.ServiceCall call, $async.Future<$0.LogRequest> request) async* {\n    yield* logListener(call, await request);\n  }\n\n  $async.Future<$1.Empty> close_Pre(\n      $grpc.ServiceCall call, $async.Future<$0.CloseRequest> request) async {\n    return close(call, await request);\n  }\n\n  $async.Future<$0.CoreInfoResponse> start(\n      $grpc.ServiceCall call, $0.StartRequest request);\n  $async.Stream<$0.CoreInfoResponse> coreInfoListener(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Stream<$0.OutboundGroupList> outboundsInfo(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Stream<$0.OutboundGroupList> mainOutboundsInfo(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Future<$0.SystemInfo> getSystemInfo(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Stream<$0.SystemInfo> getSystemInfoStream(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Future<$1.Response> setup(\n      $grpc.ServiceCall call, $0.SetupRequest request);\n  $async.Future<$0.ParseResponse> parse(\n      $grpc.ServiceCall call, $0.ParseRequest request);\n  $async.Future<$0.CoreInfoResponse> changeHiddifySettings(\n      $grpc.ServiceCall call, $0.ChangeHiddifySettingsRequest request);\n  $async.Future<$0.CoreInfoResponse> startService(\n      $grpc.ServiceCall call, $0.StartRequest request);\n  $async.Future<$0.CoreInfoResponse> stop(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Future<$0.CoreInfoResponse> restart(\n      $grpc.ServiceCall call, $0.StartRequest request);\n  $async.Future<$1.Response> selectOutbound(\n      $grpc.ServiceCall call, $0.SelectOutboundRequest request);\n  $async.Future<$1.Response> urlTest(\n      $grpc.ServiceCall call, $0.UrlTestRequest request);\n  $async.Future<$1.Response> urlTestActive(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Future<$0.WarpGenerationResponse> generateWarpConfig(\n      $grpc.ServiceCall call, $0.GenerateWarpConfigRequest request);\n  $async.Future<$0.SystemProxyStatus> getSystemProxyStatus(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Future<$1.Response> setSystemProxyEnabled(\n      $grpc.ServiceCall call, $0.SetSystemProxyEnabledRequest request);\n  $async.Stream<$0.LogMessage> logListener(\n      $grpc.ServiceCall call, $0.LogRequest request);\n  $async.Future<$1.Empty> close(\n      $grpc.ServiceCall call, $0.CloseRequest request);\n}\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/hcore_service.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/hcore_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/tunnelservice/tunnel.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/tunnelservice/tunnel.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nclass TunnelStartRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TunnelStartRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'tunnelservice'), createEmptyInstance: create)\n    ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ipv6')\n    ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serverPort', $pb.PbFieldType.O3)\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serverUsername')\n    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serverPassword')\n    ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'strictRoute')\n    ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'endpointIndependentNat')\n    ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'stack')\n    ..hasRequiredFields = false\n  ;\n\n  TunnelStartRequest._() : super();\n  factory TunnelStartRequest({\n    $core.bool? ipv6,\n    $core.int? serverPort,\n    $core.String? serverUsername,\n    $core.String? serverPassword,\n    $core.bool? strictRoute,\n    $core.bool? endpointIndependentNat,\n    $core.String? stack,\n  }) {\n    final _result = create();\n    if (ipv6 != null) {\n      _result.ipv6 = ipv6;\n    }\n    if (serverPort != null) {\n      _result.serverPort = serverPort;\n    }\n    if (serverUsername != null) {\n      _result.serverUsername = serverUsername;\n    }\n    if (serverPassword != null) {\n      _result.serverPassword = serverPassword;\n    }\n    if (strictRoute != null) {\n      _result.strictRoute = strictRoute;\n    }\n    if (endpointIndependentNat != null) {\n      _result.endpointIndependentNat = endpointIndependentNat;\n    }\n    if (stack != null) {\n      _result.stack = stack;\n    }\n    return _result;\n  }\n  factory TunnelStartRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory TunnelStartRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  TunnelStartRequest clone() => TunnelStartRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  TunnelStartRequest copyWith(void Function(TunnelStartRequest) updates) => super.copyWith((message) => updates(message as TunnelStartRequest)) as TunnelStartRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static TunnelStartRequest create() => TunnelStartRequest._();\n  TunnelStartRequest createEmptyInstance() => create();\n  static $pb.PbList<TunnelStartRequest> createRepeated() => $pb.PbList<TunnelStartRequest>();\n  @$core.pragma('dart2js:noInline')\n  static TunnelStartRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<TunnelStartRequest>(create);\n  static TunnelStartRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.bool get ipv6 => $_getBF(0);\n  @$pb.TagNumber(1)\n  set ipv6($core.bool v) { $_setBool(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasIpv6() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearIpv6() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.int get serverPort => $_getIZ(1);\n  @$pb.TagNumber(2)\n  set serverPort($core.int v) { $_setSignedInt32(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasServerPort() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearServerPort() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get serverUsername => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set serverUsername($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasServerUsername() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearServerUsername() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.String get serverPassword => $_getSZ(3);\n  @$pb.TagNumber(4)\n  set serverPassword($core.String v) { $_setString(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasServerPassword() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearServerPassword() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.bool get strictRoute => $_getBF(4);\n  @$pb.TagNumber(5)\n  set strictRoute($core.bool v) { $_setBool(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasStrictRoute() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearStrictRoute() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $core.bool get endpointIndependentNat => $_getBF(5);\n  @$pb.TagNumber(6)\n  set endpointIndependentNat($core.bool v) { $_setBool(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasEndpointIndependentNat() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearEndpointIndependentNat() => clearField(6);\n\n  @$pb.TagNumber(7)\n  $core.String get stack => $_getSZ(6);\n  @$pb.TagNumber(7)\n  set stack($core.String v) { $_setString(6, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasStack() => $_has(6);\n  @$pb.TagNumber(7)\n  void clearStack() => clearField(7);\n}\n\nclass TunnelResponse extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TunnelResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'tunnelservice'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message')\n    ..hasRequiredFields = false\n  ;\n\n  TunnelResponse._() : super();\n  factory TunnelResponse({\n    $core.String? message,\n  }) {\n    final _result = create();\n    if (message != null) {\n      _result.message = message;\n    }\n    return _result;\n  }\n  factory TunnelResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory TunnelResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  TunnelResponse clone() => TunnelResponse()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  TunnelResponse copyWith(void Function(TunnelResponse) updates) => super.copyWith((message) => updates(message as TunnelResponse)) as TunnelResponse; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static TunnelResponse create() => TunnelResponse._();\n  TunnelResponse createEmptyInstance() => create();\n  static $pb.PbList<TunnelResponse> createRepeated() => $pb.PbList<TunnelResponse>();\n  @$core.pragma('dart2js:noInline')\n  static TunnelResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<TunnelResponse>(create);\n  static TunnelResponse? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get message => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set message($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasMessage() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearMessage() => clearField(1);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/tunnelservice/tunnel.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/tunnelservice/tunnel.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/tunnelservice/tunnel.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/tunnelservice/tunnel.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n@$core.Deprecated('Use tunnelStartRequestDescriptor instead')\nconst TunnelStartRequest$json = const {\n  '1': 'TunnelStartRequest',\n  '2': const [\n    const {'1': 'ipv6', '3': 1, '4': 1, '5': 8, '10': 'ipv6'},\n    const {'1': 'server_port', '3': 2, '4': 1, '5': 5, '10': 'serverPort'},\n    const {'1': 'server_username', '3': 3, '4': 1, '5': 9, '10': 'serverUsername'},\n    const {'1': 'server_password', '3': 4, '4': 1, '5': 9, '10': 'serverPassword'},\n    const {'1': 'strict_route', '3': 5, '4': 1, '5': 8, '10': 'strictRoute'},\n    const {'1': 'endpoint_independent_nat', '3': 6, '4': 1, '5': 8, '10': 'endpointIndependentNat'},\n    const {'1': 'stack', '3': 7, '4': 1, '5': 9, '10': 'stack'},\n  ],\n};\n\n/// Descriptor for `TunnelStartRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List tunnelStartRequestDescriptor = $convert.base64Decode('ChJUdW5uZWxTdGFydFJlcXVlc3QSEgoEaXB2NhgBIAEoCFIEaXB2NhIfCgtzZXJ2ZXJfcG9ydBgCIAEoBVIKc2VydmVyUG9ydBInCg9zZXJ2ZXJfdXNlcm5hbWUYAyABKAlSDnNlcnZlclVzZXJuYW1lEicKD3NlcnZlcl9wYXNzd29yZBgEIAEoCVIOc2VydmVyUGFzc3dvcmQSIQoMc3RyaWN0X3JvdXRlGAUgASgIUgtzdHJpY3RSb3V0ZRI4ChhlbmRwb2ludF9pbmRlcGVuZGVudF9uYXQYBiABKAhSFmVuZHBvaW50SW5kZXBlbmRlbnROYXQSFAoFc3RhY2sYByABKAlSBXN0YWNr');\n@$core.Deprecated('Use tunnelResponseDescriptor instead')\nconst TunnelResponse$json = const {\n  '1': 'TunnelResponse',\n  '2': const [\n    const {'1': 'message', '3': 1, '4': 1, '5': 9, '10': 'message'},\n  ],\n};\n\n/// Descriptor for `TunnelResponse`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List tunnelResponseDescriptor = $convert.base64Decode('Cg5UdW5uZWxSZXNwb25zZRIYCgdtZXNzYWdlGAEgASgJUgdtZXNzYWdl');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/tunnelservice/tunnel_service.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/tunnelservice/tunnel_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/tunnelservice/tunnel_service.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/tunnelservice/tunnel_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/tunnelservice/tunnel_service.pbgrpc.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/tunnelservice/tunnel_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:async' as $async;\n\nimport 'dart:core' as $core;\n\nimport 'package:grpc/service_api.dart' as $grpc;\nimport 'tunnel.pb.dart' as $2;\nimport '../../hcommon/common.pb.dart' as $1;\nexport 'tunnel_service.pb.dart';\n\nclass TunnelServiceClient extends $grpc.Client {\n  static final _$start =\n      $grpc.ClientMethod<$2.TunnelStartRequest, $2.TunnelResponse>(\n          '/tunnelservice.TunnelService/Start',\n          ($2.TunnelStartRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) => $2.TunnelResponse.fromBuffer(value));\n  static final _$stop = $grpc.ClientMethod<$1.Empty, $2.TunnelResponse>(\n      '/tunnelservice.TunnelService/Stop',\n      ($1.Empty value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $2.TunnelResponse.fromBuffer(value));\n  static final _$status = $grpc.ClientMethod<$1.Empty, $2.TunnelResponse>(\n      '/tunnelservice.TunnelService/Status',\n      ($1.Empty value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $2.TunnelResponse.fromBuffer(value));\n  static final _$exit = $grpc.ClientMethod<$1.Empty, $2.TunnelResponse>(\n      '/tunnelservice.TunnelService/Exit',\n      ($1.Empty value) => value.writeToBuffer(),\n      ($core.List<$core.int> value) => $2.TunnelResponse.fromBuffer(value));\n\n  TunnelServiceClient($grpc.ClientChannel channel,\n      {$grpc.CallOptions? options,\n      $core.Iterable<$grpc.ClientInterceptor>? interceptors})\n      : super(channel, options: options, interceptors: interceptors);\n\n  $grpc.ResponseFuture<$2.TunnelResponse> start($2.TunnelStartRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$start, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$2.TunnelResponse> stop($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$stop, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$2.TunnelResponse> status($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$status, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$2.TunnelResponse> exit($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$exit, request, options: options);\n  }\n}\n\nabstract class TunnelServiceBase extends $grpc.Service {\n  $core.String get $name => 'tunnelservice.TunnelService';\n\n  TunnelServiceBase() {\n    $addMethod($grpc.ServiceMethod<$2.TunnelStartRequest, $2.TunnelResponse>(\n        'Start',\n        start_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) =>\n            $2.TunnelStartRequest.fromBuffer(value),\n        ($2.TunnelResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $2.TunnelResponse>(\n        'Stop',\n        stop_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($2.TunnelResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $2.TunnelResponse>(\n        'Status',\n        status_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($2.TunnelResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $2.TunnelResponse>(\n        'Exit',\n        exit_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($2.TunnelResponse value) => value.writeToBuffer()));\n  }\n\n  $async.Future<$2.TunnelResponse> start_Pre($grpc.ServiceCall call,\n      $async.Future<$2.TunnelStartRequest> request) async {\n    return start(call, await request);\n  }\n\n  $async.Future<$2.TunnelResponse> stop_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async {\n    return stop(call, await request);\n  }\n\n  $async.Future<$2.TunnelResponse> status_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async {\n    return status(call, await request);\n  }\n\n  $async.Future<$2.TunnelResponse> exit_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async {\n    return exit(call, await request);\n  }\n\n  $async.Future<$2.TunnelResponse> start(\n      $grpc.ServiceCall call, $2.TunnelStartRequest request);\n  $async.Future<$2.TunnelResponse> stop(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Future<$2.TunnelResponse> status(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Future<$2.TunnelResponse> exit(\n      $grpc.ServiceCall call, $1.Empty request);\n}\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hcore/tunnelservice/tunnel_service.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hcore/tunnelservice/tunnel_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hello/hello.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hello/hello.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nclass HelloRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'HelloRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hello'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')\n    ..hasRequiredFields = false\n  ;\n\n  HelloRequest._() : super();\n  factory HelloRequest({\n    $core.String? name,\n  }) {\n    final _result = create();\n    if (name != null) {\n      _result.name = name;\n    }\n    return _result;\n  }\n  factory HelloRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory HelloRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  HelloRequest clone() => HelloRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  HelloRequest copyWith(void Function(HelloRequest) updates) => super.copyWith((message) => updates(message as HelloRequest)) as HelloRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static HelloRequest create() => HelloRequest._();\n  HelloRequest createEmptyInstance() => create();\n  static $pb.PbList<HelloRequest> createRepeated() => $pb.PbList<HelloRequest>();\n  @$core.pragma('dart2js:noInline')\n  static HelloRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<HelloRequest>(create);\n  static HelloRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get name => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set name($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasName() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearName() => clearField(1);\n}\n\nclass HelloResponse extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'HelloResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hello'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message')\n    ..hasRequiredFields = false\n  ;\n\n  HelloResponse._() : super();\n  factory HelloResponse({\n    $core.String? message,\n  }) {\n    final _result = create();\n    if (message != null) {\n      _result.message = message;\n    }\n    return _result;\n  }\n  factory HelloResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory HelloResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  HelloResponse clone() => HelloResponse()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  HelloResponse copyWith(void Function(HelloResponse) updates) => super.copyWith((message) => updates(message as HelloResponse)) as HelloResponse; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static HelloResponse create() => HelloResponse._();\n  HelloResponse createEmptyInstance() => create();\n  static $pb.PbList<HelloResponse> createRepeated() => $pb.PbList<HelloResponse>();\n  @$core.pragma('dart2js:noInline')\n  static HelloResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<HelloResponse>(create);\n  static HelloResponse? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get message => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set message($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasMessage() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearMessage() => clearField(1);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hello/hello.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hello/hello.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hello/hello.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hello/hello.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n@$core.Deprecated('Use helloRequestDescriptor instead')\nconst HelloRequest$json = const {\n  '1': 'HelloRequest',\n  '2': const [\n    const {'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'},\n  ],\n};\n\n/// Descriptor for `HelloRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List helloRequestDescriptor = $convert.base64Decode('CgxIZWxsb1JlcXVlc3QSEgoEbmFtZRgBIAEoCVIEbmFtZQ==');\n@$core.Deprecated('Use helloResponseDescriptor instead')\nconst HelloResponse$json = const {\n  '1': 'HelloResponse',\n  '2': const [\n    const {'1': 'message', '3': 1, '4': 1, '5': 9, '10': 'message'},\n  ],\n};\n\n/// Descriptor for `HelloResponse`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List helloResponseDescriptor = $convert.base64Decode('Cg1IZWxsb1Jlc3BvbnNlEhgKB21lc3NhZ2UYASABKAlSB21lc3NhZ2U=');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hello/hello_service.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hello/hello_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hello/hello_service.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hello/hello_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hello/hello_service.pbgrpc.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hello/hello_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:async' as $async;\n\nimport 'dart:core' as $core;\n\nimport 'package:grpc/service_api.dart' as $grpc;\nimport 'hello.pb.dart' as $5;\nexport 'hello_service.pb.dart';\n\nclass HelloClient extends $grpc.Client {\n  static final _$sayHello =\n      $grpc.ClientMethod<$5.HelloRequest, $5.HelloResponse>(\n          '/hello.Hello/SayHello',\n          ($5.HelloRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) => $5.HelloResponse.fromBuffer(value));\n  static final _$sayHelloStream =\n      $grpc.ClientMethod<$5.HelloRequest, $5.HelloResponse>(\n          '/hello.Hello/SayHelloStream',\n          ($5.HelloRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) => $5.HelloResponse.fromBuffer(value));\n\n  HelloClient($grpc.ClientChannel channel,\n      {$grpc.CallOptions? options,\n      $core.Iterable<$grpc.ClientInterceptor>? interceptors})\n      : super(channel, options: options, interceptors: interceptors);\n\n  $grpc.ResponseFuture<$5.HelloResponse> sayHello($5.HelloRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$sayHello, request, options: options);\n  }\n\n  $grpc.ResponseStream<$5.HelloResponse> sayHelloStream(\n      $async.Stream<$5.HelloRequest> request,\n      {$grpc.CallOptions? options}) {\n    return $createStreamingCall(_$sayHelloStream, request, options: options);\n  }\n}\n\nabstract class HelloServiceBase extends $grpc.Service {\n  $core.String get $name => 'hello.Hello';\n\n  HelloServiceBase() {\n    $addMethod($grpc.ServiceMethod<$5.HelloRequest, $5.HelloResponse>(\n        'SayHello',\n        sayHello_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $5.HelloRequest.fromBuffer(value),\n        ($5.HelloResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$5.HelloRequest, $5.HelloResponse>(\n        'SayHelloStream',\n        sayHelloStream,\n        true,\n        true,\n        ($core.List<$core.int> value) => $5.HelloRequest.fromBuffer(value),\n        ($5.HelloResponse value) => value.writeToBuffer()));\n  }\n\n  $async.Future<$5.HelloResponse> sayHello_Pre(\n      $grpc.ServiceCall call, $async.Future<$5.HelloRequest> request) async {\n    return sayHello(call, await request);\n  }\n\n  $async.Future<$5.HelloResponse> sayHello(\n      $grpc.ServiceCall call, $5.HelloRequest request);\n  $async.Stream<$5.HelloResponse> sayHelloStream(\n      $grpc.ServiceCall call, $async.Stream<$5.HelloRequest> request);\n}\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hello/hello_service.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hello/hello_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hiddifyoptions/hiddify_options.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hiddifyoptions/hiddify_options.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\nimport 'package:fixnum/fixnum.dart' as $fixnum;\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nimport 'hiddify_options.pbenum.dart';\n\nexport 'hiddify_options.pbenum.dart';\n\nclass HiddifyOptions extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'HiddifyOptions', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enableFullConfig')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'logLevel')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'logFile')\n    ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enableClashApi')\n    ..a<$core.int>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'clashApiPort', $pb.PbFieldType.OU3)\n    ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'webSecret')\n    ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'region')\n    ..aOB(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockAds')\n    ..aOB(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'useXrayCoreWhenPossible')\n    ..pc<Rule>(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rules', $pb.PbFieldType.PM, subBuilder: Rule.create)\n    ..aOM<WarpOptions>(11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'warp', subBuilder: WarpOptions.create)\n    ..aOM<WarpOptions>(12, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'warp2', subBuilder: WarpOptions.create)\n    ..aOM<MuxOptions>(13, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mux', subBuilder: MuxOptions.create)\n    ..aOM<TLSTricks>(14, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'tlsTricks', subBuilder: TLSTricks.create)\n    ..aOM<DNSOptions>(15, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dnsOptions', subBuilder: DNSOptions.create)\n    ..aOM<InboundOptions>(16, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'inboundOptions', subBuilder: InboundOptions.create)\n    ..aOM<URLTestOptions>(17, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'urlTestOptions', subBuilder: URLTestOptions.create)\n    ..aOM<RouteOptions>(18, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'routeOptions', subBuilder: RouteOptions.create)\n    ..hasRequiredFields = false\n  ;\n\n  HiddifyOptions._() : super();\n  factory HiddifyOptions({\n    $core.bool? enableFullConfig,\n    $core.String? logLevel,\n    $core.String? logFile,\n    $core.bool? enableClashApi,\n    $core.int? clashApiPort,\n    $core.String? webSecret,\n    $core.String? region,\n    $core.bool? blockAds,\n    $core.bool? useXrayCoreWhenPossible,\n    $core.Iterable<Rule>? rules,\n    WarpOptions? warp,\n    WarpOptions? warp2,\n    MuxOptions? mux,\n    TLSTricks? tlsTricks,\n    DNSOptions? dnsOptions,\n    InboundOptions? inboundOptions,\n    URLTestOptions? urlTestOptions,\n    RouteOptions? routeOptions,\n  }) {\n    final _result = create();\n    if (enableFullConfig != null) {\n      _result.enableFullConfig = enableFullConfig;\n    }\n    if (logLevel != null) {\n      _result.logLevel = logLevel;\n    }\n    if (logFile != null) {\n      _result.logFile = logFile;\n    }\n    if (enableClashApi != null) {\n      _result.enableClashApi = enableClashApi;\n    }\n    if (clashApiPort != null) {\n      _result.clashApiPort = clashApiPort;\n    }\n    if (webSecret != null) {\n      _result.webSecret = webSecret;\n    }\n    if (region != null) {\n      _result.region = region;\n    }\n    if (blockAds != null) {\n      _result.blockAds = blockAds;\n    }\n    if (useXrayCoreWhenPossible != null) {\n      _result.useXrayCoreWhenPossible = useXrayCoreWhenPossible;\n    }\n    if (rules != null) {\n      _result.rules.addAll(rules);\n    }\n    if (warp != null) {\n      _result.warp = warp;\n    }\n    if (warp2 != null) {\n      _result.warp2 = warp2;\n    }\n    if (mux != null) {\n      _result.mux = mux;\n    }\n    if (tlsTricks != null) {\n      _result.tlsTricks = tlsTricks;\n    }\n    if (dnsOptions != null) {\n      _result.dnsOptions = dnsOptions;\n    }\n    if (inboundOptions != null) {\n      _result.inboundOptions = inboundOptions;\n    }\n    if (urlTestOptions != null) {\n      _result.urlTestOptions = urlTestOptions;\n    }\n    if (routeOptions != null) {\n      _result.routeOptions = routeOptions;\n    }\n    return _result;\n  }\n  factory HiddifyOptions.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory HiddifyOptions.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  HiddifyOptions clone() => HiddifyOptions()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  HiddifyOptions copyWith(void Function(HiddifyOptions) updates) => super.copyWith((message) => updates(message as HiddifyOptions)) as HiddifyOptions; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static HiddifyOptions create() => HiddifyOptions._();\n  HiddifyOptions createEmptyInstance() => create();\n  static $pb.PbList<HiddifyOptions> createRepeated() => $pb.PbList<HiddifyOptions>();\n  @$core.pragma('dart2js:noInline')\n  static HiddifyOptions getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<HiddifyOptions>(create);\n  static HiddifyOptions? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.bool get enableFullConfig => $_getBF(0);\n  @$pb.TagNumber(1)\n  set enableFullConfig($core.bool v) { $_setBool(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasEnableFullConfig() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearEnableFullConfig() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get logLevel => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set logLevel($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasLogLevel() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearLogLevel() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get logFile => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set logFile($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasLogFile() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearLogFile() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.bool get enableClashApi => $_getBF(3);\n  @$pb.TagNumber(4)\n  set enableClashApi($core.bool v) { $_setBool(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasEnableClashApi() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearEnableClashApi() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.int get clashApiPort => $_getIZ(4);\n  @$pb.TagNumber(5)\n  set clashApiPort($core.int v) { $_setUnsignedInt32(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasClashApiPort() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearClashApiPort() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $core.String get webSecret => $_getSZ(5);\n  @$pb.TagNumber(6)\n  set webSecret($core.String v) { $_setString(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasWebSecret() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearWebSecret() => clearField(6);\n\n  @$pb.TagNumber(7)\n  $core.String get region => $_getSZ(6);\n  @$pb.TagNumber(7)\n  set region($core.String v) { $_setString(6, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasRegion() => $_has(6);\n  @$pb.TagNumber(7)\n  void clearRegion() => clearField(7);\n\n  @$pb.TagNumber(8)\n  $core.bool get blockAds => $_getBF(7);\n  @$pb.TagNumber(8)\n  set blockAds($core.bool v) { $_setBool(7, v); }\n  @$pb.TagNumber(8)\n  $core.bool hasBlockAds() => $_has(7);\n  @$pb.TagNumber(8)\n  void clearBlockAds() => clearField(8);\n\n  @$pb.TagNumber(9)\n  $core.bool get useXrayCoreWhenPossible => $_getBF(8);\n  @$pb.TagNumber(9)\n  set useXrayCoreWhenPossible($core.bool v) { $_setBool(8, v); }\n  @$pb.TagNumber(9)\n  $core.bool hasUseXrayCoreWhenPossible() => $_has(8);\n  @$pb.TagNumber(9)\n  void clearUseXrayCoreWhenPossible() => clearField(9);\n\n  @$pb.TagNumber(10)\n  $core.List<Rule> get rules => $_getList(9);\n\n  @$pb.TagNumber(11)\n  WarpOptions get warp => $_getN(10);\n  @$pb.TagNumber(11)\n  set warp(WarpOptions v) { setField(11, v); }\n  @$pb.TagNumber(11)\n  $core.bool hasWarp() => $_has(10);\n  @$pb.TagNumber(11)\n  void clearWarp() => clearField(11);\n  @$pb.TagNumber(11)\n  WarpOptions ensureWarp() => $_ensure(10);\n\n  @$pb.TagNumber(12)\n  WarpOptions get warp2 => $_getN(11);\n  @$pb.TagNumber(12)\n  set warp2(WarpOptions v) { setField(12, v); }\n  @$pb.TagNumber(12)\n  $core.bool hasWarp2() => $_has(11);\n  @$pb.TagNumber(12)\n  void clearWarp2() => clearField(12);\n  @$pb.TagNumber(12)\n  WarpOptions ensureWarp2() => $_ensure(11);\n\n  @$pb.TagNumber(13)\n  MuxOptions get mux => $_getN(12);\n  @$pb.TagNumber(13)\n  set mux(MuxOptions v) { setField(13, v); }\n  @$pb.TagNumber(13)\n  $core.bool hasMux() => $_has(12);\n  @$pb.TagNumber(13)\n  void clearMux() => clearField(13);\n  @$pb.TagNumber(13)\n  MuxOptions ensureMux() => $_ensure(12);\n\n  @$pb.TagNumber(14)\n  TLSTricks get tlsTricks => $_getN(13);\n  @$pb.TagNumber(14)\n  set tlsTricks(TLSTricks v) { setField(14, v); }\n  @$pb.TagNumber(14)\n  $core.bool hasTlsTricks() => $_has(13);\n  @$pb.TagNumber(14)\n  void clearTlsTricks() => clearField(14);\n  @$pb.TagNumber(14)\n  TLSTricks ensureTlsTricks() => $_ensure(13);\n\n  @$pb.TagNumber(15)\n  DNSOptions get dnsOptions => $_getN(14);\n  @$pb.TagNumber(15)\n  set dnsOptions(DNSOptions v) { setField(15, v); }\n  @$pb.TagNumber(15)\n  $core.bool hasDnsOptions() => $_has(14);\n  @$pb.TagNumber(15)\n  void clearDnsOptions() => clearField(15);\n  @$pb.TagNumber(15)\n  DNSOptions ensureDnsOptions() => $_ensure(14);\n\n  @$pb.TagNumber(16)\n  InboundOptions get inboundOptions => $_getN(15);\n  @$pb.TagNumber(16)\n  set inboundOptions(InboundOptions v) { setField(16, v); }\n  @$pb.TagNumber(16)\n  $core.bool hasInboundOptions() => $_has(15);\n  @$pb.TagNumber(16)\n  void clearInboundOptions() => clearField(16);\n  @$pb.TagNumber(16)\n  InboundOptions ensureInboundOptions() => $_ensure(15);\n\n  @$pb.TagNumber(17)\n  URLTestOptions get urlTestOptions => $_getN(16);\n  @$pb.TagNumber(17)\n  set urlTestOptions(URLTestOptions v) { setField(17, v); }\n  @$pb.TagNumber(17)\n  $core.bool hasUrlTestOptions() => $_has(16);\n  @$pb.TagNumber(17)\n  void clearUrlTestOptions() => clearField(17);\n  @$pb.TagNumber(17)\n  URLTestOptions ensureUrlTestOptions() => $_ensure(16);\n\n  @$pb.TagNumber(18)\n  RouteOptions get routeOptions => $_getN(17);\n  @$pb.TagNumber(18)\n  set routeOptions(RouteOptions v) { setField(18, v); }\n  @$pb.TagNumber(18)\n  $core.bool hasRouteOptions() => $_has(17);\n  @$pb.TagNumber(18)\n  void clearRouteOptions() => clearField(18);\n  @$pb.TagNumber(18)\n  RouteOptions ensureRouteOptions() => $_ensure(17);\n}\n\nclass IntRange extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'IntRange', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'from', $pb.PbFieldType.O3)\n    ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'to', $pb.PbFieldType.O3)\n    ..hasRequiredFields = false\n  ;\n\n  IntRange._() : super();\n  factory IntRange({\n    $core.int? from,\n    $core.int? to,\n  }) {\n    final _result = create();\n    if (from != null) {\n      _result.from = from;\n    }\n    if (to != null) {\n      _result.to = to;\n    }\n    return _result;\n  }\n  factory IntRange.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory IntRange.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  IntRange clone() => IntRange()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  IntRange copyWith(void Function(IntRange) updates) => super.copyWith((message) => updates(message as IntRange)) as IntRange; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static IntRange create() => IntRange._();\n  IntRange createEmptyInstance() => create();\n  static $pb.PbList<IntRange> createRepeated() => $pb.PbList<IntRange>();\n  @$core.pragma('dart2js:noInline')\n  static IntRange getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<IntRange>(create);\n  static IntRange? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.int get from => $_getIZ(0);\n  @$pb.TagNumber(1)\n  set from($core.int v) { $_setSignedInt32(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasFrom() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearFrom() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.int get to => $_getIZ(1);\n  @$pb.TagNumber(2)\n  set to($core.int v) { $_setSignedInt32(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasTo() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearTo() => clearField(2);\n}\n\nclass DNSOptions extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DNSOptions', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'remoteDnsAddress')\n    ..e<DomainStrategy>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'remoteDnsDomainStrategy', $pb.PbFieldType.OE, defaultOrMaker: DomainStrategy.as_is, valueOf: DomainStrategy.valueOf, enumValues: DomainStrategy.values)\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'directDnsAddress')\n    ..e<DomainStrategy>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'directDnsDomainStrategy', $pb.PbFieldType.OE, defaultOrMaker: DomainStrategy.as_is, valueOf: DomainStrategy.valueOf, enumValues: DomainStrategy.values)\n    ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'independentDnsCache')\n    ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enableFakeDns')\n    ..aOB(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enableDnsRouting')\n    ..hasRequiredFields = false\n  ;\n\n  DNSOptions._() : super();\n  factory DNSOptions({\n    $core.String? remoteDnsAddress,\n    DomainStrategy? remoteDnsDomainStrategy,\n    $core.String? directDnsAddress,\n    DomainStrategy? directDnsDomainStrategy,\n    $core.bool? independentDnsCache,\n    $core.bool? enableFakeDns,\n    $core.bool? enableDnsRouting,\n  }) {\n    final _result = create();\n    if (remoteDnsAddress != null) {\n      _result.remoteDnsAddress = remoteDnsAddress;\n    }\n    if (remoteDnsDomainStrategy != null) {\n      _result.remoteDnsDomainStrategy = remoteDnsDomainStrategy;\n    }\n    if (directDnsAddress != null) {\n      _result.directDnsAddress = directDnsAddress;\n    }\n    if (directDnsDomainStrategy != null) {\n      _result.directDnsDomainStrategy = directDnsDomainStrategy;\n    }\n    if (independentDnsCache != null) {\n      _result.independentDnsCache = independentDnsCache;\n    }\n    if (enableFakeDns != null) {\n      _result.enableFakeDns = enableFakeDns;\n    }\n    if (enableDnsRouting != null) {\n      _result.enableDnsRouting = enableDnsRouting;\n    }\n    return _result;\n  }\n  factory DNSOptions.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory DNSOptions.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  DNSOptions clone() => DNSOptions()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  DNSOptions copyWith(void Function(DNSOptions) updates) => super.copyWith((message) => updates(message as DNSOptions)) as DNSOptions; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static DNSOptions create() => DNSOptions._();\n  DNSOptions createEmptyInstance() => create();\n  static $pb.PbList<DNSOptions> createRepeated() => $pb.PbList<DNSOptions>();\n  @$core.pragma('dart2js:noInline')\n  static DNSOptions getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DNSOptions>(create);\n  static DNSOptions? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get remoteDnsAddress => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set remoteDnsAddress($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasRemoteDnsAddress() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearRemoteDnsAddress() => clearField(1);\n\n  @$pb.TagNumber(2)\n  DomainStrategy get remoteDnsDomainStrategy => $_getN(1);\n  @$pb.TagNumber(2)\n  set remoteDnsDomainStrategy(DomainStrategy v) { setField(2, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasRemoteDnsDomainStrategy() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearRemoteDnsDomainStrategy() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get directDnsAddress => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set directDnsAddress($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasDirectDnsAddress() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearDirectDnsAddress() => clearField(3);\n\n  @$pb.TagNumber(4)\n  DomainStrategy get directDnsDomainStrategy => $_getN(3);\n  @$pb.TagNumber(4)\n  set directDnsDomainStrategy(DomainStrategy v) { setField(4, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasDirectDnsDomainStrategy() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearDirectDnsDomainStrategy() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.bool get independentDnsCache => $_getBF(4);\n  @$pb.TagNumber(5)\n  set independentDnsCache($core.bool v) { $_setBool(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasIndependentDnsCache() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearIndependentDnsCache() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $core.bool get enableFakeDns => $_getBF(5);\n  @$pb.TagNumber(6)\n  set enableFakeDns($core.bool v) { $_setBool(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasEnableFakeDns() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearEnableFakeDns() => clearField(6);\n\n  @$pb.TagNumber(7)\n  $core.bool get enableDnsRouting => $_getBF(6);\n  @$pb.TagNumber(7)\n  set enableDnsRouting($core.bool v) { $_setBool(6, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasEnableDnsRouting() => $_has(6);\n  @$pb.TagNumber(7)\n  void clearEnableDnsRouting() => clearField(7);\n}\n\nclass InboundOptions extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'InboundOptions', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enableTun')\n    ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enableTunService')\n    ..aOB(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'setSystemProxy')\n    ..a<$core.int>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mixedPort', $pb.PbFieldType.OU3)\n    ..a<$core.int>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'tproxyPort', $pb.PbFieldType.OU3)\n    ..a<$core.int>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'directPort', $pb.PbFieldType.OU3)\n    ..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mtu', $pb.PbFieldType.OU3)\n    ..aOB(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'strictRoute')\n    ..aOS(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'tunStack')\n    ..a<$core.int>(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'redirectPort', $pb.PbFieldType.OU3)\n    ..hasRequiredFields = false\n  ;\n\n  InboundOptions._() : super();\n  factory InboundOptions({\n    $core.bool? enableTun,\n    $core.bool? enableTunService,\n    $core.bool? setSystemProxy,\n    $core.int? mixedPort,\n    $core.int? tproxyPort,\n    $core.int? directPort,\n    $core.int? mtu,\n    $core.bool? strictRoute,\n    $core.String? tunStack,\n    $core.int? redirectPort,\n  }) {\n    final _result = create();\n    if (enableTun != null) {\n      _result.enableTun = enableTun;\n    }\n    if (enableTunService != null) {\n      _result.enableTunService = enableTunService;\n    }\n    if (setSystemProxy != null) {\n      _result.setSystemProxy = setSystemProxy;\n    }\n    if (mixedPort != null) {\n      _result.mixedPort = mixedPort;\n    }\n    if (tproxyPort != null) {\n      _result.tproxyPort = tproxyPort;\n    }\n    if (directPort != null) {\n      _result.directPort = directPort;\n    }\n    if (mtu != null) {\n      _result.mtu = mtu;\n    }\n    if (strictRoute != null) {\n      _result.strictRoute = strictRoute;\n    }\n    if (tunStack != null) {\n      _result.tunStack = tunStack;\n    }\n    if (redirectPort != null) {\n      _result.redirectPort = redirectPort;\n    }\n    return _result;\n  }\n  factory InboundOptions.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory InboundOptions.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  InboundOptions clone() => InboundOptions()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  InboundOptions copyWith(void Function(InboundOptions) updates) => super.copyWith((message) => updates(message as InboundOptions)) as InboundOptions; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static InboundOptions create() => InboundOptions._();\n  InboundOptions createEmptyInstance() => create();\n  static $pb.PbList<InboundOptions> createRepeated() => $pb.PbList<InboundOptions>();\n  @$core.pragma('dart2js:noInline')\n  static InboundOptions getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<InboundOptions>(create);\n  static InboundOptions? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.bool get enableTun => $_getBF(0);\n  @$pb.TagNumber(1)\n  set enableTun($core.bool v) { $_setBool(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasEnableTun() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearEnableTun() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.bool get enableTunService => $_getBF(1);\n  @$pb.TagNumber(2)\n  set enableTunService($core.bool v) { $_setBool(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasEnableTunService() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearEnableTunService() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.bool get setSystemProxy => $_getBF(2);\n  @$pb.TagNumber(3)\n  set setSystemProxy($core.bool v) { $_setBool(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasSetSystemProxy() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearSetSystemProxy() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.int get mixedPort => $_getIZ(3);\n  @$pb.TagNumber(4)\n  set mixedPort($core.int v) { $_setUnsignedInt32(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasMixedPort() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearMixedPort() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.int get tproxyPort => $_getIZ(4);\n  @$pb.TagNumber(5)\n  set tproxyPort($core.int v) { $_setUnsignedInt32(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasTproxyPort() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearTproxyPort() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $core.int get directPort => $_getIZ(5);\n  @$pb.TagNumber(6)\n  set directPort($core.int v) { $_setUnsignedInt32(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasDirectPort() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearDirectPort() => clearField(6);\n\n  @$pb.TagNumber(7)\n  $core.int get mtu => $_getIZ(6);\n  @$pb.TagNumber(7)\n  set mtu($core.int v) { $_setUnsignedInt32(6, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasMtu() => $_has(6);\n  @$pb.TagNumber(7)\n  void clearMtu() => clearField(7);\n\n  @$pb.TagNumber(8)\n  $core.bool get strictRoute => $_getBF(7);\n  @$pb.TagNumber(8)\n  set strictRoute($core.bool v) { $_setBool(7, v); }\n  @$pb.TagNumber(8)\n  $core.bool hasStrictRoute() => $_has(7);\n  @$pb.TagNumber(8)\n  void clearStrictRoute() => clearField(8);\n\n  @$pb.TagNumber(9)\n  $core.String get tunStack => $_getSZ(8);\n  @$pb.TagNumber(9)\n  set tunStack($core.String v) { $_setString(8, v); }\n  @$pb.TagNumber(9)\n  $core.bool hasTunStack() => $_has(8);\n  @$pb.TagNumber(9)\n  void clearTunStack() => clearField(9);\n\n  @$pb.TagNumber(10)\n  $core.int get redirectPort => $_getIZ(9);\n  @$pb.TagNumber(10)\n  set redirectPort($core.int v) { $_setUnsignedInt32(9, v); }\n  @$pb.TagNumber(10)\n  $core.bool hasRedirectPort() => $_has(9);\n  @$pb.TagNumber(10)\n  void clearRedirectPort() => clearField(10);\n}\n\nclass URLTestOptions extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'URLTestOptions', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'connectionTestUrl')\n    ..aInt64(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'urlTestInterval')\n    ..hasRequiredFields = false\n  ;\n\n  URLTestOptions._() : super();\n  factory URLTestOptions({\n    $core.String? connectionTestUrl,\n    $fixnum.Int64? urlTestInterval,\n  }) {\n    final _result = create();\n    if (connectionTestUrl != null) {\n      _result.connectionTestUrl = connectionTestUrl;\n    }\n    if (urlTestInterval != null) {\n      _result.urlTestInterval = urlTestInterval;\n    }\n    return _result;\n  }\n  factory URLTestOptions.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory URLTestOptions.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  URLTestOptions clone() => URLTestOptions()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  URLTestOptions copyWith(void Function(URLTestOptions) updates) => super.copyWith((message) => updates(message as URLTestOptions)) as URLTestOptions; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static URLTestOptions create() => URLTestOptions._();\n  URLTestOptions createEmptyInstance() => create();\n  static $pb.PbList<URLTestOptions> createRepeated() => $pb.PbList<URLTestOptions>();\n  @$core.pragma('dart2js:noInline')\n  static URLTestOptions getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<URLTestOptions>(create);\n  static URLTestOptions? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get connectionTestUrl => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set connectionTestUrl($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasConnectionTestUrl() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearConnectionTestUrl() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $fixnum.Int64 get urlTestInterval => $_getI64(1);\n  @$pb.TagNumber(2)\n  set urlTestInterval($fixnum.Int64 v) { $_setInt64(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasUrlTestInterval() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearUrlTestInterval() => clearField(2);\n}\n\nclass RouteOptions extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RouteOptions', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'resolveDestination')\n    ..e<DomainStrategy>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ipv6Mode', $pb.PbFieldType.OE, defaultOrMaker: DomainStrategy.as_is, valueOf: DomainStrategy.valueOf, enumValues: DomainStrategy.values)\n    ..aOB(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'bypassLan')\n    ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'allowConnectionFromLan')\n    ..hasRequiredFields = false\n  ;\n\n  RouteOptions._() : super();\n  factory RouteOptions({\n    $core.bool? resolveDestination,\n    DomainStrategy? ipv6Mode,\n    $core.bool? bypassLan,\n    $core.bool? allowConnectionFromLan,\n  }) {\n    final _result = create();\n    if (resolveDestination != null) {\n      _result.resolveDestination = resolveDestination;\n    }\n    if (ipv6Mode != null) {\n      _result.ipv6Mode = ipv6Mode;\n    }\n    if (bypassLan != null) {\n      _result.bypassLan = bypassLan;\n    }\n    if (allowConnectionFromLan != null) {\n      _result.allowConnectionFromLan = allowConnectionFromLan;\n    }\n    return _result;\n  }\n  factory RouteOptions.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory RouteOptions.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  RouteOptions clone() => RouteOptions()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  RouteOptions copyWith(void Function(RouteOptions) updates) => super.copyWith((message) => updates(message as RouteOptions)) as RouteOptions; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static RouteOptions create() => RouteOptions._();\n  RouteOptions createEmptyInstance() => create();\n  static $pb.PbList<RouteOptions> createRepeated() => $pb.PbList<RouteOptions>();\n  @$core.pragma('dart2js:noInline')\n  static RouteOptions getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RouteOptions>(create);\n  static RouteOptions? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.bool get resolveDestination => $_getBF(0);\n  @$pb.TagNumber(1)\n  set resolveDestination($core.bool v) { $_setBool(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasResolveDestination() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearResolveDestination() => clearField(1);\n\n  @$pb.TagNumber(2)\n  DomainStrategy get ipv6Mode => $_getN(1);\n  @$pb.TagNumber(2)\n  set ipv6Mode(DomainStrategy v) { setField(2, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasIpv6Mode() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearIpv6Mode() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.bool get bypassLan => $_getBF(2);\n  @$pb.TagNumber(3)\n  set bypassLan($core.bool v) { $_setBool(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasBypassLan() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearBypassLan() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.bool get allowConnectionFromLan => $_getBF(3);\n  @$pb.TagNumber(4)\n  set allowConnectionFromLan($core.bool v) { $_setBool(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasAllowConnectionFromLan() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearAllowConnectionFromLan() => clearField(4);\n}\n\nclass TLSTricks extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TLSTricks', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enableFragment')\n    ..aOM<IntRange>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fragmentSize', subBuilder: IntRange.create)\n    ..aOM<IntRange>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fragmentSleep', subBuilder: IntRange.create)\n    ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mixedSniCase')\n    ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enablePadding')\n    ..aOM<IntRange>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'paddingSize', subBuilder: IntRange.create)\n    ..hasRequiredFields = false\n  ;\n\n  TLSTricks._() : super();\n  factory TLSTricks({\n    $core.bool? enableFragment,\n    IntRange? fragmentSize,\n    IntRange? fragmentSleep,\n    $core.bool? mixedSniCase,\n    $core.bool? enablePadding,\n    IntRange? paddingSize,\n  }) {\n    final _result = create();\n    if (enableFragment != null) {\n      _result.enableFragment = enableFragment;\n    }\n    if (fragmentSize != null) {\n      _result.fragmentSize = fragmentSize;\n    }\n    if (fragmentSleep != null) {\n      _result.fragmentSleep = fragmentSleep;\n    }\n    if (mixedSniCase != null) {\n      _result.mixedSniCase = mixedSniCase;\n    }\n    if (enablePadding != null) {\n      _result.enablePadding = enablePadding;\n    }\n    if (paddingSize != null) {\n      _result.paddingSize = paddingSize;\n    }\n    return _result;\n  }\n  factory TLSTricks.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory TLSTricks.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  TLSTricks clone() => TLSTricks()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  TLSTricks copyWith(void Function(TLSTricks) updates) => super.copyWith((message) => updates(message as TLSTricks)) as TLSTricks; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static TLSTricks create() => TLSTricks._();\n  TLSTricks createEmptyInstance() => create();\n  static $pb.PbList<TLSTricks> createRepeated() => $pb.PbList<TLSTricks>();\n  @$core.pragma('dart2js:noInline')\n  static TLSTricks getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<TLSTricks>(create);\n  static TLSTricks? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.bool get enableFragment => $_getBF(0);\n  @$pb.TagNumber(1)\n  set enableFragment($core.bool v) { $_setBool(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasEnableFragment() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearEnableFragment() => clearField(1);\n\n  @$pb.TagNumber(2)\n  IntRange get fragmentSize => $_getN(1);\n  @$pb.TagNumber(2)\n  set fragmentSize(IntRange v) { setField(2, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasFragmentSize() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearFragmentSize() => clearField(2);\n  @$pb.TagNumber(2)\n  IntRange ensureFragmentSize() => $_ensure(1);\n\n  @$pb.TagNumber(3)\n  IntRange get fragmentSleep => $_getN(2);\n  @$pb.TagNumber(3)\n  set fragmentSleep(IntRange v) { setField(3, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasFragmentSleep() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearFragmentSleep() => clearField(3);\n  @$pb.TagNumber(3)\n  IntRange ensureFragmentSleep() => $_ensure(2);\n\n  @$pb.TagNumber(4)\n  $core.bool get mixedSniCase => $_getBF(3);\n  @$pb.TagNumber(4)\n  set mixedSniCase($core.bool v) { $_setBool(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasMixedSniCase() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearMixedSniCase() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.bool get enablePadding => $_getBF(4);\n  @$pb.TagNumber(5)\n  set enablePadding($core.bool v) { $_setBool(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasEnablePadding() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearEnablePadding() => clearField(5);\n\n  @$pb.TagNumber(6)\n  IntRange get paddingSize => $_getN(5);\n  @$pb.TagNumber(6)\n  set paddingSize(IntRange v) { setField(6, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasPaddingSize() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearPaddingSize() => clearField(6);\n  @$pb.TagNumber(6)\n  IntRange ensurePaddingSize() => $_ensure(5);\n}\n\nclass MuxOptions extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'MuxOptions', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enable')\n    ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'padding')\n    ..a<$core.int>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'maxStreams', $pb.PbFieldType.O3)\n    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'protocol')\n    ..hasRequiredFields = false\n  ;\n\n  MuxOptions._() : super();\n  factory MuxOptions({\n    $core.bool? enable,\n    $core.bool? padding,\n    $core.int? maxStreams,\n    $core.String? protocol,\n  }) {\n    final _result = create();\n    if (enable != null) {\n      _result.enable = enable;\n    }\n    if (padding != null) {\n      _result.padding = padding;\n    }\n    if (maxStreams != null) {\n      _result.maxStreams = maxStreams;\n    }\n    if (protocol != null) {\n      _result.protocol = protocol;\n    }\n    return _result;\n  }\n  factory MuxOptions.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory MuxOptions.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  MuxOptions clone() => MuxOptions()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  MuxOptions copyWith(void Function(MuxOptions) updates) => super.copyWith((message) => updates(message as MuxOptions)) as MuxOptions; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static MuxOptions create() => MuxOptions._();\n  MuxOptions createEmptyInstance() => create();\n  static $pb.PbList<MuxOptions> createRepeated() => $pb.PbList<MuxOptions>();\n  @$core.pragma('dart2js:noInline')\n  static MuxOptions getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MuxOptions>(create);\n  static MuxOptions? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.bool get enable => $_getBF(0);\n  @$pb.TagNumber(1)\n  set enable($core.bool v) { $_setBool(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasEnable() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearEnable() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.bool get padding => $_getBF(1);\n  @$pb.TagNumber(2)\n  set padding($core.bool v) { $_setBool(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasPadding() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearPadding() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.int get maxStreams => $_getIZ(2);\n  @$pb.TagNumber(3)\n  set maxStreams($core.int v) { $_setSignedInt32(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasMaxStreams() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearMaxStreams() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.String get protocol => $_getSZ(3);\n  @$pb.TagNumber(4)\n  set protocol($core.String v) { $_setString(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasProtocol() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearProtocol() => clearField(4);\n}\n\nclass WarpOptions extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WarpOptions', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')\n    ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'enableWarp')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mode')\n    ..aOM<WarpWireguardConfig>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'wireguardConfig', subBuilder: WarpWireguardConfig.create)\n    ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fakePackets')\n    ..aOM<IntRange>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fakePacketSize', subBuilder: IntRange.create)\n    ..aOM<IntRange>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fakePacketDelay', subBuilder: IntRange.create)\n    ..aOS(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fakePacketMode')\n    ..aOS(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'cleanIp')\n    ..a<$core.int>(11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'cleanPort', $pb.PbFieldType.OU3)\n    ..aOM<WarpAccount>(12, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'account', subBuilder: WarpAccount.create)\n    ..hasRequiredFields = false\n  ;\n\n  WarpOptions._() : super();\n  factory WarpOptions({\n    $core.String? id,\n    $core.bool? enableWarp,\n    $core.String? mode,\n    WarpWireguardConfig? wireguardConfig,\n    $core.String? fakePackets,\n    IntRange? fakePacketSize,\n    IntRange? fakePacketDelay,\n    $core.String? fakePacketMode,\n    $core.String? cleanIp,\n    $core.int? cleanPort,\n    WarpAccount? account,\n  }) {\n    final _result = create();\n    if (id != null) {\n      _result.id = id;\n    }\n    if (enableWarp != null) {\n      _result.enableWarp = enableWarp;\n    }\n    if (mode != null) {\n      _result.mode = mode;\n    }\n    if (wireguardConfig != null) {\n      _result.wireguardConfig = wireguardConfig;\n    }\n    if (fakePackets != null) {\n      _result.fakePackets = fakePackets;\n    }\n    if (fakePacketSize != null) {\n      _result.fakePacketSize = fakePacketSize;\n    }\n    if (fakePacketDelay != null) {\n      _result.fakePacketDelay = fakePacketDelay;\n    }\n    if (fakePacketMode != null) {\n      _result.fakePacketMode = fakePacketMode;\n    }\n    if (cleanIp != null) {\n      _result.cleanIp = cleanIp;\n    }\n    if (cleanPort != null) {\n      _result.cleanPort = cleanPort;\n    }\n    if (account != null) {\n      _result.account = account;\n    }\n    return _result;\n  }\n  factory WarpOptions.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory WarpOptions.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  WarpOptions clone() => WarpOptions()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  WarpOptions copyWith(void Function(WarpOptions) updates) => super.copyWith((message) => updates(message as WarpOptions)) as WarpOptions; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static WarpOptions create() => WarpOptions._();\n  WarpOptions createEmptyInstance() => create();\n  static $pb.PbList<WarpOptions> createRepeated() => $pb.PbList<WarpOptions>();\n  @$core.pragma('dart2js:noInline')\n  static WarpOptions getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<WarpOptions>(create);\n  static WarpOptions? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get id => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set id($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasId() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearId() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.bool get enableWarp => $_getBF(1);\n  @$pb.TagNumber(2)\n  set enableWarp($core.bool v) { $_setBool(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasEnableWarp() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearEnableWarp() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get mode => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set mode($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasMode() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearMode() => clearField(3);\n\n  @$pb.TagNumber(5)\n  WarpWireguardConfig get wireguardConfig => $_getN(3);\n  @$pb.TagNumber(5)\n  set wireguardConfig(WarpWireguardConfig v) { setField(5, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasWireguardConfig() => $_has(3);\n  @$pb.TagNumber(5)\n  void clearWireguardConfig() => clearField(5);\n  @$pb.TagNumber(5)\n  WarpWireguardConfig ensureWireguardConfig() => $_ensure(3);\n\n  @$pb.TagNumber(6)\n  $core.String get fakePackets => $_getSZ(4);\n  @$pb.TagNumber(6)\n  set fakePackets($core.String v) { $_setString(4, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasFakePackets() => $_has(4);\n  @$pb.TagNumber(6)\n  void clearFakePackets() => clearField(6);\n\n  @$pb.TagNumber(7)\n  IntRange get fakePacketSize => $_getN(5);\n  @$pb.TagNumber(7)\n  set fakePacketSize(IntRange v) { setField(7, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasFakePacketSize() => $_has(5);\n  @$pb.TagNumber(7)\n  void clearFakePacketSize() => clearField(7);\n  @$pb.TagNumber(7)\n  IntRange ensureFakePacketSize() => $_ensure(5);\n\n  @$pb.TagNumber(8)\n  IntRange get fakePacketDelay => $_getN(6);\n  @$pb.TagNumber(8)\n  set fakePacketDelay(IntRange v) { setField(8, v); }\n  @$pb.TagNumber(8)\n  $core.bool hasFakePacketDelay() => $_has(6);\n  @$pb.TagNumber(8)\n  void clearFakePacketDelay() => clearField(8);\n  @$pb.TagNumber(8)\n  IntRange ensureFakePacketDelay() => $_ensure(6);\n\n  @$pb.TagNumber(9)\n  $core.String get fakePacketMode => $_getSZ(7);\n  @$pb.TagNumber(9)\n  set fakePacketMode($core.String v) { $_setString(7, v); }\n  @$pb.TagNumber(9)\n  $core.bool hasFakePacketMode() => $_has(7);\n  @$pb.TagNumber(9)\n  void clearFakePacketMode() => clearField(9);\n\n  @$pb.TagNumber(10)\n  $core.String get cleanIp => $_getSZ(8);\n  @$pb.TagNumber(10)\n  set cleanIp($core.String v) { $_setString(8, v); }\n  @$pb.TagNumber(10)\n  $core.bool hasCleanIp() => $_has(8);\n  @$pb.TagNumber(10)\n  void clearCleanIp() => clearField(10);\n\n  @$pb.TagNumber(11)\n  $core.int get cleanPort => $_getIZ(9);\n  @$pb.TagNumber(11)\n  set cleanPort($core.int v) { $_setUnsignedInt32(9, v); }\n  @$pb.TagNumber(11)\n  $core.bool hasCleanPort() => $_has(9);\n  @$pb.TagNumber(11)\n  void clearCleanPort() => clearField(11);\n\n  @$pb.TagNumber(12)\n  WarpAccount get account => $_getN(10);\n  @$pb.TagNumber(12)\n  set account(WarpAccount v) { setField(12, v); }\n  @$pb.TagNumber(12)\n  $core.bool hasAccount() => $_has(10);\n  @$pb.TagNumber(12)\n  void clearAccount() => clearField(12);\n  @$pb.TagNumber(12)\n  WarpAccount ensureAccount() => $_ensure(10);\n}\n\nclass WarpAccount extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WarpAccount', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'accountId')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'accessToken')\n    ..hasRequiredFields = false\n  ;\n\n  WarpAccount._() : super();\n  factory WarpAccount({\n    $core.String? accountId,\n    $core.String? accessToken,\n  }) {\n    final _result = create();\n    if (accountId != null) {\n      _result.accountId = accountId;\n    }\n    if (accessToken != null) {\n      _result.accessToken = accessToken;\n    }\n    return _result;\n  }\n  factory WarpAccount.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory WarpAccount.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  WarpAccount clone() => WarpAccount()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  WarpAccount copyWith(void Function(WarpAccount) updates) => super.copyWith((message) => updates(message as WarpAccount)) as WarpAccount; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static WarpAccount create() => WarpAccount._();\n  WarpAccount createEmptyInstance() => create();\n  static $pb.PbList<WarpAccount> createRepeated() => $pb.PbList<WarpAccount>();\n  @$core.pragma('dart2js:noInline')\n  static WarpAccount getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<WarpAccount>(create);\n  static WarpAccount? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get accountId => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set accountId($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasAccountId() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearAccountId() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get accessToken => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set accessToken($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasAccessToken() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearAccessToken() => clearField(2);\n}\n\nclass WarpWireguardConfig extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WarpWireguardConfig', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'privateKey')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'localAddressIpv4')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'localAddressIpv6')\n    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'peerPublicKey')\n    ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'clientId')\n    ..hasRequiredFields = false\n  ;\n\n  WarpWireguardConfig._() : super();\n  factory WarpWireguardConfig({\n    $core.String? privateKey,\n    $core.String? localAddressIpv4,\n    $core.String? localAddressIpv6,\n    $core.String? peerPublicKey,\n    $core.String? clientId,\n  }) {\n    final _result = create();\n    if (privateKey != null) {\n      _result.privateKey = privateKey;\n    }\n    if (localAddressIpv4 != null) {\n      _result.localAddressIpv4 = localAddressIpv4;\n    }\n    if (localAddressIpv6 != null) {\n      _result.localAddressIpv6 = localAddressIpv6;\n    }\n    if (peerPublicKey != null) {\n      _result.peerPublicKey = peerPublicKey;\n    }\n    if (clientId != null) {\n      _result.clientId = clientId;\n    }\n    return _result;\n  }\n  factory WarpWireguardConfig.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory WarpWireguardConfig.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  WarpWireguardConfig clone() => WarpWireguardConfig()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  WarpWireguardConfig copyWith(void Function(WarpWireguardConfig) updates) => super.copyWith((message) => updates(message as WarpWireguardConfig)) as WarpWireguardConfig; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static WarpWireguardConfig create() => WarpWireguardConfig._();\n  WarpWireguardConfig createEmptyInstance() => create();\n  static $pb.PbList<WarpWireguardConfig> createRepeated() => $pb.PbList<WarpWireguardConfig>();\n  @$core.pragma('dart2js:noInline')\n  static WarpWireguardConfig getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<WarpWireguardConfig>(create);\n  static WarpWireguardConfig? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get privateKey => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set privateKey($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasPrivateKey() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearPrivateKey() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get localAddressIpv4 => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set localAddressIpv4($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasLocalAddressIpv4() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearLocalAddressIpv4() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get localAddressIpv6 => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set localAddressIpv6($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasLocalAddressIpv6() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearLocalAddressIpv6() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.String get peerPublicKey => $_getSZ(3);\n  @$pb.TagNumber(4)\n  set peerPublicKey($core.String v) { $_setString(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasPeerPublicKey() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearPeerPublicKey() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.String get clientId => $_getSZ(4);\n  @$pb.TagNumber(5)\n  set clientId($core.String v) { $_setString(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasClientId() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearClientId() => clearField(5);\n}\n\nclass Rule extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Rule', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'hiddifyoptions'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ruleSetUrl')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'domains')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ip')\n    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'port')\n    ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'network')\n    ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'protocol')\n    ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'outbound')\n    ..hasRequiredFields = false\n  ;\n\n  Rule._() : super();\n  factory Rule({\n    $core.String? ruleSetUrl,\n    $core.String? domains,\n    $core.String? ip,\n    $core.String? port,\n    $core.String? network,\n    $core.String? protocol,\n    $core.String? outbound,\n  }) {\n    final _result = create();\n    if (ruleSetUrl != null) {\n      _result.ruleSetUrl = ruleSetUrl;\n    }\n    if (domains != null) {\n      _result.domains = domains;\n    }\n    if (ip != null) {\n      _result.ip = ip;\n    }\n    if (port != null) {\n      _result.port = port;\n    }\n    if (network != null) {\n      _result.network = network;\n    }\n    if (protocol != null) {\n      _result.protocol = protocol;\n    }\n    if (outbound != null) {\n      _result.outbound = outbound;\n    }\n    return _result;\n  }\n  factory Rule.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory Rule.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  Rule clone() => Rule()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  Rule copyWith(void Function(Rule) updates) => super.copyWith((message) => updates(message as Rule)) as Rule; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static Rule create() => Rule._();\n  Rule createEmptyInstance() => create();\n  static $pb.PbList<Rule> createRepeated() => $pb.PbList<Rule>();\n  @$core.pragma('dart2js:noInline')\n  static Rule getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Rule>(create);\n  static Rule? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get ruleSetUrl => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set ruleSetUrl($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasRuleSetUrl() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearRuleSetUrl() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get domains => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set domains($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasDomains() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearDomains() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get ip => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set ip($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasIp() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearIp() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.String get port => $_getSZ(3);\n  @$pb.TagNumber(4)\n  set port($core.String v) { $_setString(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasPort() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearPort() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.String get network => $_getSZ(4);\n  @$pb.TagNumber(5)\n  set network($core.String v) { $_setString(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasNetwork() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearNetwork() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $core.String get protocol => $_getSZ(5);\n  @$pb.TagNumber(6)\n  set protocol($core.String v) { $_setString(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasProtocol() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearProtocol() => clearField(6);\n\n  @$pb.TagNumber(7)\n  $core.String get outbound => $_getSZ(6);\n  @$pb.TagNumber(7)\n  set outbound($core.String v) { $_setString(6, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasOutbound() => $_has(6);\n  @$pb.TagNumber(7)\n  void clearOutbound() => clearField(7);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hiddifyoptions/hiddify_options.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hiddifyoptions/hiddify_options.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n// ignore_for_file: UNDEFINED_SHOWN_NAME\nimport 'dart:core' as $core;\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nclass DomainStrategy extends $pb.ProtobufEnum {\n  static const DomainStrategy as_is = DomainStrategy._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'as_is');\n  static const DomainStrategy prefer_ipv4 = DomainStrategy._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'prefer_ipv4');\n  static const DomainStrategy prefer_ipv6 = DomainStrategy._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'prefer_ipv6');\n  static const DomainStrategy ipv4_only = DomainStrategy._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ipv4_only');\n  static const DomainStrategy ipv6_only = DomainStrategy._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ipv6_only');\n\n  static const $core.List<DomainStrategy> values = <DomainStrategy> [\n    as_is,\n    prefer_ipv4,\n    prefer_ipv6,\n    ipv4_only,\n    ipv6_only,\n  ];\n\n  static final $core.Map<$core.int, DomainStrategy> _byValue = $pb.ProtobufEnum.initByValue(values);\n  static DomainStrategy? valueOf($core.int value) => _byValue[value];\n\n  const DomainStrategy._($core.int v, $core.String n) : super(v, n);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/hiddifyoptions/hiddify_options.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/hiddifyoptions/hiddify_options.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n@$core.Deprecated('Use domainStrategyDescriptor instead')\nconst DomainStrategy$json = const {\n  '1': 'DomainStrategy',\n  '2': const [\n    const {'1': 'as_is', '2': 0},\n    const {'1': 'prefer_ipv4', '2': 1},\n    const {'1': 'prefer_ipv6', '2': 2},\n    const {'1': 'ipv4_only', '2': 3},\n    const {'1': 'ipv6_only', '2': 4},\n  ],\n};\n\n/// Descriptor for `DomainStrategy`. Decode as a `google.protobuf.EnumDescriptorProto`.\nfinal $typed_data.Uint8List domainStrategyDescriptor = $convert.base64Decode('Cg5Eb21haW5TdHJhdGVneRIJCgVhc19pcxAAEg8KC3ByZWZlcl9pcHY0EAESDwoLcHJlZmVyX2lwdjYQAhINCglpcHY0X29ubHkQAxINCglpcHY2X29ubHkQBA==');\n@$core.Deprecated('Use hiddifyOptionsDescriptor instead')\nconst HiddifyOptions$json = const {\n  '1': 'HiddifyOptions',\n  '2': const [\n    const {'1': 'enable_full_config', '3': 1, '4': 1, '5': 8, '10': 'enableFullConfig'},\n    const {'1': 'log_level', '3': 2, '4': 1, '5': 9, '10': 'logLevel'},\n    const {'1': 'log_file', '3': 3, '4': 1, '5': 9, '10': 'logFile'},\n    const {'1': 'enable_clash_api', '3': 4, '4': 1, '5': 8, '10': 'enableClashApi'},\n    const {'1': 'clash_api_port', '3': 5, '4': 1, '5': 13, '10': 'clashApiPort'},\n    const {'1': 'web_secret', '3': 6, '4': 1, '5': 9, '10': 'webSecret'},\n    const {'1': 'region', '3': 7, '4': 1, '5': 9, '10': 'region'},\n    const {'1': 'block_ads', '3': 8, '4': 1, '5': 8, '10': 'blockAds'},\n    const {'1': 'use_xray_core_when_possible', '3': 9, '4': 1, '5': 8, '10': 'useXrayCoreWhenPossible'},\n    const {'1': 'rules', '3': 10, '4': 3, '5': 11, '6': '.hiddifyoptions.Rule', '10': 'rules'},\n    const {'1': 'warp', '3': 11, '4': 1, '5': 11, '6': '.hiddifyoptions.WarpOptions', '10': 'warp'},\n    const {'1': 'warp2', '3': 12, '4': 1, '5': 11, '6': '.hiddifyoptions.WarpOptions', '10': 'warp2'},\n    const {'1': 'mux', '3': 13, '4': 1, '5': 11, '6': '.hiddifyoptions.MuxOptions', '10': 'mux'},\n    const {'1': 'tls_tricks', '3': 14, '4': 1, '5': 11, '6': '.hiddifyoptions.TLSTricks', '10': 'tlsTricks'},\n    const {'1': 'dns_options', '3': 15, '4': 1, '5': 11, '6': '.hiddifyoptions.DNSOptions', '10': 'dnsOptions'},\n    const {'1': 'inbound_options', '3': 16, '4': 1, '5': 11, '6': '.hiddifyoptions.InboundOptions', '10': 'inboundOptions'},\n    const {'1': 'url_test_options', '3': 17, '4': 1, '5': 11, '6': '.hiddifyoptions.URLTestOptions', '10': 'urlTestOptions'},\n    const {'1': 'route_options', '3': 18, '4': 1, '5': 11, '6': '.hiddifyoptions.RouteOptions', '10': 'routeOptions'},\n  ],\n};\n\n/// Descriptor for `HiddifyOptions`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List hiddifyOptionsDescriptor = $convert.base64Decode('Cg5IaWRkaWZ5T3B0aW9ucxIsChJlbmFibGVfZnVsbF9jb25maWcYASABKAhSEGVuYWJsZUZ1bGxDb25maWcSGwoJbG9nX2xldmVsGAIgASgJUghsb2dMZXZlbBIZCghsb2dfZmlsZRgDIAEoCVIHbG9nRmlsZRIoChBlbmFibGVfY2xhc2hfYXBpGAQgASgIUg5lbmFibGVDbGFzaEFwaRIkCg5jbGFzaF9hcGlfcG9ydBgFIAEoDVIMY2xhc2hBcGlQb3J0Eh0KCndlYl9zZWNyZXQYBiABKAlSCXdlYlNlY3JldBIWCgZyZWdpb24YByABKAlSBnJlZ2lvbhIbCglibG9ja19hZHMYCCABKAhSCGJsb2NrQWRzEjwKG3VzZV94cmF5X2NvcmVfd2hlbl9wb3NzaWJsZRgJIAEoCFIXdXNlWHJheUNvcmVXaGVuUG9zc2libGUSKgoFcnVsZXMYCiADKAsyFC5oaWRkaWZ5b3B0aW9ucy5SdWxlUgVydWxlcxIvCgR3YXJwGAsgASgLMhsuaGlkZGlmeW9wdGlvbnMuV2FycE9wdGlvbnNSBHdhcnASMQoFd2FycDIYDCABKAsyGy5oaWRkaWZ5b3B0aW9ucy5XYXJwT3B0aW9uc1IFd2FycDISLAoDbXV4GA0gASgLMhouaGlkZGlmeW9wdGlvbnMuTXV4T3B0aW9uc1IDbXV4EjgKCnRsc190cmlja3MYDiABKAsyGS5oaWRkaWZ5b3B0aW9ucy5UTFNUcmlja3NSCXRsc1RyaWNrcxI7CgtkbnNfb3B0aW9ucxgPIAEoCzIaLmhpZGRpZnlvcHRpb25zLkROU09wdGlvbnNSCmRuc09wdGlvbnMSRwoPaW5ib3VuZF9vcHRpb25zGBAgASgLMh4uaGlkZGlmeW9wdGlvbnMuSW5ib3VuZE9wdGlvbnNSDmluYm91bmRPcHRpb25zEkgKEHVybF90ZXN0X29wdGlvbnMYESABKAsyHi5oaWRkaWZ5b3B0aW9ucy5VUkxUZXN0T3B0aW9uc1IOdXJsVGVzdE9wdGlvbnMSQQoNcm91dGVfb3B0aW9ucxgSIAEoCzIcLmhpZGRpZnlvcHRpb25zLlJvdXRlT3B0aW9uc1IMcm91dGVPcHRpb25z');\n@$core.Deprecated('Use intRangeDescriptor instead')\nconst IntRange$json = const {\n  '1': 'IntRange',\n  '2': const [\n    const {'1': 'from', '3': 1, '4': 1, '5': 5, '10': 'from'},\n    const {'1': 'to', '3': 2, '4': 1, '5': 5, '10': 'to'},\n  ],\n};\n\n/// Descriptor for `IntRange`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List intRangeDescriptor = $convert.base64Decode('CghJbnRSYW5nZRISCgRmcm9tGAEgASgFUgRmcm9tEg4KAnRvGAIgASgFUgJ0bw==');\n@$core.Deprecated('Use dNSOptionsDescriptor instead')\nconst DNSOptions$json = const {\n  '1': 'DNSOptions',\n  '2': const [\n    const {'1': 'remote_dns_address', '3': 1, '4': 1, '5': 9, '10': 'remoteDnsAddress'},\n    const {'1': 'remote_dns_domain_strategy', '3': 2, '4': 1, '5': 14, '6': '.hiddifyoptions.DomainStrategy', '10': 'remoteDnsDomainStrategy'},\n    const {'1': 'direct_dns_address', '3': 3, '4': 1, '5': 9, '10': 'directDnsAddress'},\n    const {'1': 'direct_dns_domain_strategy', '3': 4, '4': 1, '5': 14, '6': '.hiddifyoptions.DomainStrategy', '10': 'directDnsDomainStrategy'},\n    const {'1': 'independent_dns_cache', '3': 5, '4': 1, '5': 8, '10': 'independentDnsCache'},\n    const {'1': 'enable_fake_dns', '3': 6, '4': 1, '5': 8, '10': 'enableFakeDns'},\n    const {'1': 'enable_dns_routing', '3': 7, '4': 1, '5': 8, '10': 'enableDnsRouting'},\n  ],\n};\n\n/// Descriptor for `DNSOptions`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List dNSOptionsDescriptor = $convert.base64Decode('CgpETlNPcHRpb25zEiwKEnJlbW90ZV9kbnNfYWRkcmVzcxgBIAEoCVIQcmVtb3RlRG5zQWRkcmVzcxJbChpyZW1vdGVfZG5zX2RvbWFpbl9zdHJhdGVneRgCIAEoDjIeLmhpZGRpZnlvcHRpb25zLkRvbWFpblN0cmF0ZWd5UhdyZW1vdGVEbnNEb21haW5TdHJhdGVneRIsChJkaXJlY3RfZG5zX2FkZHJlc3MYAyABKAlSEGRpcmVjdERuc0FkZHJlc3MSWwoaZGlyZWN0X2Ruc19kb21haW5fc3RyYXRlZ3kYBCABKA4yHi5oaWRkaWZ5b3B0aW9ucy5Eb21haW5TdHJhdGVneVIXZGlyZWN0RG5zRG9tYWluU3RyYXRlZ3kSMgoVaW5kZXBlbmRlbnRfZG5zX2NhY2hlGAUgASgIUhNpbmRlcGVuZGVudERuc0NhY2hlEiYKD2VuYWJsZV9mYWtlX2RucxgGIAEoCFINZW5hYmxlRmFrZURucxIsChJlbmFibGVfZG5zX3JvdXRpbmcYByABKAhSEGVuYWJsZURuc1JvdXRpbmc=');\n@$core.Deprecated('Use inboundOptionsDescriptor instead')\nconst InboundOptions$json = const {\n  '1': 'InboundOptions',\n  '2': const [\n    const {'1': 'enable_tun', '3': 1, '4': 1, '5': 8, '10': 'enableTun'},\n    const {'1': 'enable_tun_service', '3': 2, '4': 1, '5': 8, '10': 'enableTunService'},\n    const {'1': 'set_system_proxy', '3': 3, '4': 1, '5': 8, '10': 'setSystemProxy'},\n    const {'1': 'mixed_port', '3': 4, '4': 1, '5': 13, '10': 'mixedPort'},\n    const {'1': 'tproxy_port', '3': 5, '4': 1, '5': 13, '10': 'tproxyPort'},\n    const {'1': 'redirect_port', '3': 10, '4': 1, '5': 13, '10': 'redirectPort'},\n    const {'1': 'direct_port', '3': 6, '4': 1, '5': 13, '10': 'directPort'},\n    const {'1': 'mtu', '3': 7, '4': 1, '5': 13, '10': 'mtu'},\n    const {'1': 'strict_route', '3': 8, '4': 1, '5': 8, '10': 'strictRoute'},\n    const {'1': 'tun_stack', '3': 9, '4': 1, '5': 9, '10': 'tunStack'},\n  ],\n};\n\n/// Descriptor for `InboundOptions`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List inboundOptionsDescriptor = $convert.base64Decode('Cg5JbmJvdW5kT3B0aW9ucxIdCgplbmFibGVfdHVuGAEgASgIUgllbmFibGVUdW4SLAoSZW5hYmxlX3R1bl9zZXJ2aWNlGAIgASgIUhBlbmFibGVUdW5TZXJ2aWNlEigKEHNldF9zeXN0ZW1fcHJveHkYAyABKAhSDnNldFN5c3RlbVByb3h5Eh0KCm1peGVkX3BvcnQYBCABKA1SCW1peGVkUG9ydBIfCgt0cHJveHlfcG9ydBgFIAEoDVIKdHByb3h5UG9ydBIjCg1yZWRpcmVjdF9wb3J0GAogASgNUgxyZWRpcmVjdFBvcnQSHwoLZGlyZWN0X3BvcnQYBiABKA1SCmRpcmVjdFBvcnQSEAoDbXR1GAcgASgNUgNtdHUSIQoMc3RyaWN0X3JvdXRlGAggASgIUgtzdHJpY3RSb3V0ZRIbCgl0dW5fc3RhY2sYCSABKAlSCHR1blN0YWNr');\n@$core.Deprecated('Use uRLTestOptionsDescriptor instead')\nconst URLTestOptions$json = const {\n  '1': 'URLTestOptions',\n  '2': const [\n    const {'1': 'connection_test_url', '3': 1, '4': 1, '5': 9, '10': 'connectionTestUrl'},\n    const {'1': 'url_test_interval', '3': 2, '4': 1, '5': 3, '10': 'urlTestInterval'},\n  ],\n};\n\n/// Descriptor for `URLTestOptions`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List uRLTestOptionsDescriptor = $convert.base64Decode('Cg5VUkxUZXN0T3B0aW9ucxIuChNjb25uZWN0aW9uX3Rlc3RfdXJsGAEgASgJUhFjb25uZWN0aW9uVGVzdFVybBIqChF1cmxfdGVzdF9pbnRlcnZhbBgCIAEoA1IPdXJsVGVzdEludGVydmFs');\n@$core.Deprecated('Use routeOptionsDescriptor instead')\nconst RouteOptions$json = const {\n  '1': 'RouteOptions',\n  '2': const [\n    const {'1': 'resolve_destination', '3': 1, '4': 1, '5': 8, '10': 'resolveDestination'},\n    const {'1': 'ipv6_mode', '3': 2, '4': 1, '5': 14, '6': '.hiddifyoptions.DomainStrategy', '10': 'ipv6Mode'},\n    const {'1': 'bypass_lan', '3': 3, '4': 1, '5': 8, '10': 'bypassLan'},\n    const {'1': 'allow_connection_from_lan', '3': 4, '4': 1, '5': 8, '10': 'allowConnectionFromLan'},\n  ],\n};\n\n/// Descriptor for `RouteOptions`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List routeOptionsDescriptor = $convert.base64Decode('CgxSb3V0ZU9wdGlvbnMSLwoTcmVzb2x2ZV9kZXN0aW5hdGlvbhgBIAEoCFIScmVzb2x2ZURlc3RpbmF0aW9uEjsKCWlwdjZfbW9kZRgCIAEoDjIeLmhpZGRpZnlvcHRpb25zLkRvbWFpblN0cmF0ZWd5UghpcHY2TW9kZRIdCgpieXBhc3NfbGFuGAMgASgIUglieXBhc3NMYW4SOQoZYWxsb3dfY29ubmVjdGlvbl9mcm9tX2xhbhgEIAEoCFIWYWxsb3dDb25uZWN0aW9uRnJvbUxhbg==');\n@$core.Deprecated('Use tLSTricksDescriptor instead')\nconst TLSTricks$json = const {\n  '1': 'TLSTricks',\n  '2': const [\n    const {'1': 'enable_fragment', '3': 1, '4': 1, '5': 8, '10': 'enableFragment'},\n    const {'1': 'fragment_size', '3': 2, '4': 1, '5': 11, '6': '.hiddifyoptions.IntRange', '10': 'fragmentSize'},\n    const {'1': 'fragment_sleep', '3': 3, '4': 1, '5': 11, '6': '.hiddifyoptions.IntRange', '10': 'fragmentSleep'},\n    const {'1': 'mixed_sni_case', '3': 4, '4': 1, '5': 8, '10': 'mixedSniCase'},\n    const {'1': 'enable_padding', '3': 5, '4': 1, '5': 8, '10': 'enablePadding'},\n    const {'1': 'padding_size', '3': 6, '4': 1, '5': 11, '6': '.hiddifyoptions.IntRange', '10': 'paddingSize'},\n  ],\n};\n\n/// Descriptor for `TLSTricks`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List tLSTricksDescriptor = $convert.base64Decode('CglUTFNUcmlja3MSJwoPZW5hYmxlX2ZyYWdtZW50GAEgASgIUg5lbmFibGVGcmFnbWVudBI9Cg1mcmFnbWVudF9zaXplGAIgASgLMhguaGlkZGlmeW9wdGlvbnMuSW50UmFuZ2VSDGZyYWdtZW50U2l6ZRI/Cg5mcmFnbWVudF9zbGVlcBgDIAEoCzIYLmhpZGRpZnlvcHRpb25zLkludFJhbmdlUg1mcmFnbWVudFNsZWVwEiQKDm1peGVkX3NuaV9jYXNlGAQgASgIUgxtaXhlZFNuaUNhc2USJQoOZW5hYmxlX3BhZGRpbmcYBSABKAhSDWVuYWJsZVBhZGRpbmcSOwoMcGFkZGluZ19zaXplGAYgASgLMhguaGlkZGlmeW9wdGlvbnMuSW50UmFuZ2VSC3BhZGRpbmdTaXpl');\n@$core.Deprecated('Use muxOptionsDescriptor instead')\nconst MuxOptions$json = const {\n  '1': 'MuxOptions',\n  '2': const [\n    const {'1': 'enable', '3': 1, '4': 1, '5': 8, '10': 'enable'},\n    const {'1': 'padding', '3': 2, '4': 1, '5': 8, '10': 'padding'},\n    const {'1': 'max_streams', '3': 3, '4': 1, '5': 5, '10': 'maxStreams'},\n    const {'1': 'protocol', '3': 4, '4': 1, '5': 9, '10': 'protocol'},\n  ],\n};\n\n/// Descriptor for `MuxOptions`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List muxOptionsDescriptor = $convert.base64Decode('CgpNdXhPcHRpb25zEhYKBmVuYWJsZRgBIAEoCFIGZW5hYmxlEhgKB3BhZGRpbmcYAiABKAhSB3BhZGRpbmcSHwoLbWF4X3N0cmVhbXMYAyABKAVSCm1heFN0cmVhbXMSGgoIcHJvdG9jb2wYBCABKAlSCHByb3RvY29s');\n@$core.Deprecated('Use warpOptionsDescriptor instead')\nconst WarpOptions$json = const {\n  '1': 'WarpOptions',\n  '2': const [\n    const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},\n    const {'1': 'enable_warp', '3': 2, '4': 1, '5': 8, '10': 'enableWarp'},\n    const {'1': 'mode', '3': 3, '4': 1, '5': 9, '10': 'mode'},\n    const {'1': 'wireguard_config', '3': 5, '4': 1, '5': 11, '6': '.hiddifyoptions.WarpWireguardConfig', '10': 'wireguardConfig'},\n    const {'1': 'fake_packets', '3': 6, '4': 1, '5': 9, '10': 'fakePackets'},\n    const {'1': 'fake_packet_size', '3': 7, '4': 1, '5': 11, '6': '.hiddifyoptions.IntRange', '10': 'fakePacketSize'},\n    const {'1': 'fake_packet_delay', '3': 8, '4': 1, '5': 11, '6': '.hiddifyoptions.IntRange', '10': 'fakePacketDelay'},\n    const {'1': 'fake_packet_mode', '3': 9, '4': 1, '5': 9, '10': 'fakePacketMode'},\n    const {'1': 'clean_ip', '3': 10, '4': 1, '5': 9, '10': 'cleanIp'},\n    const {'1': 'clean_port', '3': 11, '4': 1, '5': 13, '10': 'cleanPort'},\n    const {'1': 'account', '3': 12, '4': 1, '5': 11, '6': '.hiddifyoptions.WarpAccount', '10': 'account'},\n  ],\n};\n\n/// Descriptor for `WarpOptions`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List warpOptionsDescriptor = $convert.base64Decode('CgtXYXJwT3B0aW9ucxIOCgJpZBgBIAEoCVICaWQSHwoLZW5hYmxlX3dhcnAYAiABKAhSCmVuYWJsZVdhcnASEgoEbW9kZRgDIAEoCVIEbW9kZRJOChB3aXJlZ3VhcmRfY29uZmlnGAUgASgLMiMuaGlkZGlmeW9wdGlvbnMuV2FycFdpcmVndWFyZENvbmZpZ1IPd2lyZWd1YXJkQ29uZmlnEiEKDGZha2VfcGFja2V0cxgGIAEoCVILZmFrZVBhY2tldHMSQgoQZmFrZV9wYWNrZXRfc2l6ZRgHIAEoCzIYLmhpZGRpZnlvcHRpb25zLkludFJhbmdlUg5mYWtlUGFja2V0U2l6ZRJEChFmYWtlX3BhY2tldF9kZWxheRgIIAEoCzIYLmhpZGRpZnlvcHRpb25zLkludFJhbmdlUg9mYWtlUGFja2V0RGVsYXkSKAoQZmFrZV9wYWNrZXRfbW9kZRgJIAEoCVIOZmFrZVBhY2tldE1vZGUSGQoIY2xlYW5faXAYCiABKAlSB2NsZWFuSXASHQoKY2xlYW5fcG9ydBgLIAEoDVIJY2xlYW5Qb3J0EjUKB2FjY291bnQYDCABKAsyGy5oaWRkaWZ5b3B0aW9ucy5XYXJwQWNjb3VudFIHYWNjb3VudA==');\n@$core.Deprecated('Use warpAccountDescriptor instead')\nconst WarpAccount$json = const {\n  '1': 'WarpAccount',\n  '2': const [\n    const {'1': 'account_id', '3': 1, '4': 1, '5': 9, '10': 'accountId'},\n    const {'1': 'access_token', '3': 2, '4': 1, '5': 9, '10': 'accessToken'},\n  ],\n};\n\n/// Descriptor for `WarpAccount`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List warpAccountDescriptor = $convert.base64Decode('CgtXYXJwQWNjb3VudBIdCgphY2NvdW50X2lkGAEgASgJUglhY2NvdW50SWQSIQoMYWNjZXNzX3Rva2VuGAIgASgJUgthY2Nlc3NUb2tlbg==');\n@$core.Deprecated('Use warpWireguardConfigDescriptor instead')\nconst WarpWireguardConfig$json = const {\n  '1': 'WarpWireguardConfig',\n  '2': const [\n    const {'1': 'private_key', '3': 1, '4': 1, '5': 9, '10': 'privateKey'},\n    const {'1': 'local_address_ipv4', '3': 2, '4': 1, '5': 9, '10': 'localAddressIpv4'},\n    const {'1': 'local_address_ipv6', '3': 3, '4': 1, '5': 9, '10': 'localAddressIpv6'},\n    const {'1': 'peer_public_key', '3': 4, '4': 1, '5': 9, '10': 'peerPublicKey'},\n    const {'1': 'client_id', '3': 5, '4': 1, '5': 9, '10': 'clientId'},\n  ],\n};\n\n/// Descriptor for `WarpWireguardConfig`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List warpWireguardConfigDescriptor = $convert.base64Decode('ChNXYXJwV2lyZWd1YXJkQ29uZmlnEh8KC3ByaXZhdGVfa2V5GAEgASgJUgpwcml2YXRlS2V5EiwKEmxvY2FsX2FkZHJlc3NfaXB2NBgCIAEoCVIQbG9jYWxBZGRyZXNzSXB2NBIsChJsb2NhbF9hZGRyZXNzX2lwdjYYAyABKAlSEGxvY2FsQWRkcmVzc0lwdjYSJgoPcGVlcl9wdWJsaWNfa2V5GAQgASgJUg1wZWVyUHVibGljS2V5EhsKCWNsaWVudF9pZBgFIAEoCVIIY2xpZW50SWQ=');\n@$core.Deprecated('Use ruleDescriptor instead')\nconst Rule$json = const {\n  '1': 'Rule',\n  '2': const [\n    const {'1': 'rule_set_url', '3': 1, '4': 1, '5': 9, '10': 'ruleSetUrl'},\n    const {'1': 'domains', '3': 2, '4': 1, '5': 9, '10': 'domains'},\n    const {'1': 'ip', '3': 3, '4': 1, '5': 9, '10': 'ip'},\n    const {'1': 'port', '3': 4, '4': 1, '5': 9, '10': 'port'},\n    const {'1': 'network', '3': 5, '4': 1, '5': 9, '10': 'network'},\n    const {'1': 'protocol', '3': 6, '4': 1, '5': 9, '10': 'protocol'},\n    const {'1': 'outbound', '3': 7, '4': 1, '5': 9, '10': 'outbound'},\n  ],\n};\n\n/// Descriptor for `Rule`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List ruleDescriptor = $convert.base64Decode('CgRSdWxlEiAKDHJ1bGVfc2V0X3VybBgBIAEoCVIKcnVsZVNldFVybBIYCgdkb21haW5zGAIgASgJUgdkb21haW5zEg4KAmlwGAMgASgJUgJpcBISCgRwb3J0GAQgASgJUgRwb3J0EhgKB25ldHdvcmsYBSABKAlSB25ldHdvcmsSGgoIcHJvdG9jb2wYBiABKAlSCHByb3RvY29sEhoKCG91dGJvdW5kGAcgASgJUghvdXRib3VuZA==');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/profile/profile.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/profile/profile.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\nimport 'package:fixnum/fixnum.dart' as $fixnum;\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nimport '../hiddifyoptions/hiddify_options.pb.dart' as $8;\n\nclass ProfileEntity extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ProfileEntity', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'profile'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')\n    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'url')\n    ..aInt64(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'lastUpdate')\n    ..aOM<ProfileOptions>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', subBuilder: ProfileOptions.create)\n    ..aOM<SubscriptionInfo>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'subInfo', subBuilder: SubscriptionInfo.create)\n    ..aOM<$8.HiddifyOptions>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'overrideHiddifyOptions', subBuilder: $8.HiddifyOptions.create)\n    ..hasRequiredFields = false\n  ;\n\n  ProfileEntity._() : super();\n  factory ProfileEntity({\n    $core.String? id,\n    $core.String? name,\n    $core.String? url,\n    $fixnum.Int64? lastUpdate,\n    ProfileOptions? options,\n    SubscriptionInfo? subInfo,\n    $8.HiddifyOptions? overrideHiddifyOptions,\n  }) {\n    final _result = create();\n    if (id != null) {\n      _result.id = id;\n    }\n    if (name != null) {\n      _result.name = name;\n    }\n    if (url != null) {\n      _result.url = url;\n    }\n    if (lastUpdate != null) {\n      _result.lastUpdate = lastUpdate;\n    }\n    if (options != null) {\n      _result.options = options;\n    }\n    if (subInfo != null) {\n      _result.subInfo = subInfo;\n    }\n    if (overrideHiddifyOptions != null) {\n      _result.overrideHiddifyOptions = overrideHiddifyOptions;\n    }\n    return _result;\n  }\n  factory ProfileEntity.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ProfileEntity.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ProfileEntity clone() => ProfileEntity()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ProfileEntity copyWith(void Function(ProfileEntity) updates) => super.copyWith((message) => updates(message as ProfileEntity)) as ProfileEntity; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ProfileEntity create() => ProfileEntity._();\n  ProfileEntity createEmptyInstance() => create();\n  static $pb.PbList<ProfileEntity> createRepeated() => $pb.PbList<ProfileEntity>();\n  @$core.pragma('dart2js:noInline')\n  static ProfileEntity getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ProfileEntity>(create);\n  static ProfileEntity? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get id => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set id($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasId() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearId() => clearField(1);\n\n  @$pb.TagNumber(3)\n  $core.String get name => $_getSZ(1);\n  @$pb.TagNumber(3)\n  set name($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasName() => $_has(1);\n  @$pb.TagNumber(3)\n  void clearName() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.String get url => $_getSZ(2);\n  @$pb.TagNumber(4)\n  set url($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasUrl() => $_has(2);\n  @$pb.TagNumber(4)\n  void clearUrl() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $fixnum.Int64 get lastUpdate => $_getI64(3);\n  @$pb.TagNumber(5)\n  set lastUpdate($fixnum.Int64 v) { $_setInt64(3, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasLastUpdate() => $_has(3);\n  @$pb.TagNumber(5)\n  void clearLastUpdate() => clearField(5);\n\n  @$pb.TagNumber(6)\n  ProfileOptions get options => $_getN(4);\n  @$pb.TagNumber(6)\n  set options(ProfileOptions v) { setField(6, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasOptions() => $_has(4);\n  @$pb.TagNumber(6)\n  void clearOptions() => clearField(6);\n  @$pb.TagNumber(6)\n  ProfileOptions ensureOptions() => $_ensure(4);\n\n  @$pb.TagNumber(7)\n  SubscriptionInfo get subInfo => $_getN(5);\n  @$pb.TagNumber(7)\n  set subInfo(SubscriptionInfo v) { setField(7, v); }\n  @$pb.TagNumber(7)\n  $core.bool hasSubInfo() => $_has(5);\n  @$pb.TagNumber(7)\n  void clearSubInfo() => clearField(7);\n  @$pb.TagNumber(7)\n  SubscriptionInfo ensureSubInfo() => $_ensure(5);\n\n  @$pb.TagNumber(8)\n  $8.HiddifyOptions get overrideHiddifyOptions => $_getN(6);\n  @$pb.TagNumber(8)\n  set overrideHiddifyOptions($8.HiddifyOptions v) { setField(8, v); }\n  @$pb.TagNumber(8)\n  $core.bool hasOverrideHiddifyOptions() => $_has(6);\n  @$pb.TagNumber(8)\n  void clearOverrideHiddifyOptions() => clearField(8);\n  @$pb.TagNumber(8)\n  $8.HiddifyOptions ensureOverrideHiddifyOptions() => $_ensure(6);\n}\n\nclass ProfileOptions extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ProfileOptions', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'profile'), createEmptyInstance: create)\n    ..aInt64(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'updateInterval')\n    ..hasRequiredFields = false\n  ;\n\n  ProfileOptions._() : super();\n  factory ProfileOptions({\n    $fixnum.Int64? updateInterval,\n  }) {\n    final _result = create();\n    if (updateInterval != null) {\n      _result.updateInterval = updateInterval;\n    }\n    return _result;\n  }\n  factory ProfileOptions.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ProfileOptions.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ProfileOptions clone() => ProfileOptions()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ProfileOptions copyWith(void Function(ProfileOptions) updates) => super.copyWith((message) => updates(message as ProfileOptions)) as ProfileOptions; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ProfileOptions create() => ProfileOptions._();\n  ProfileOptions createEmptyInstance() => create();\n  static $pb.PbList<ProfileOptions> createRepeated() => $pb.PbList<ProfileOptions>();\n  @$core.pragma('dart2js:noInline')\n  static ProfileOptions getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ProfileOptions>(create);\n  static ProfileOptions? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $fixnum.Int64 get updateInterval => $_getI64(0);\n  @$pb.TagNumber(1)\n  set updateInterval($fixnum.Int64 v) { $_setInt64(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasUpdateInterval() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearUpdateInterval() => clearField(1);\n}\n\nclass SubscriptionInfo extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SubscriptionInfo', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'profile'), createEmptyInstance: create)\n    ..aInt64(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'upload')\n    ..aInt64(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'download')\n    ..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'total')\n    ..aInt64(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'expire')\n    ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'webPageUrl')\n    ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'supportUrl')\n    ..hasRequiredFields = false\n  ;\n\n  SubscriptionInfo._() : super();\n  factory SubscriptionInfo({\n    $fixnum.Int64? upload,\n    $fixnum.Int64? download,\n    $fixnum.Int64? total,\n    $fixnum.Int64? expire,\n    $core.String? webPageUrl,\n    $core.String? supportUrl,\n  }) {\n    final _result = create();\n    if (upload != null) {\n      _result.upload = upload;\n    }\n    if (download != null) {\n      _result.download = download;\n    }\n    if (total != null) {\n      _result.total = total;\n    }\n    if (expire != null) {\n      _result.expire = expire;\n    }\n    if (webPageUrl != null) {\n      _result.webPageUrl = webPageUrl;\n    }\n    if (supportUrl != null) {\n      _result.supportUrl = supportUrl;\n    }\n    return _result;\n  }\n  factory SubscriptionInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory SubscriptionInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  SubscriptionInfo clone() => SubscriptionInfo()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  SubscriptionInfo copyWith(void Function(SubscriptionInfo) updates) => super.copyWith((message) => updates(message as SubscriptionInfo)) as SubscriptionInfo; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static SubscriptionInfo create() => SubscriptionInfo._();\n  SubscriptionInfo createEmptyInstance() => create();\n  static $pb.PbList<SubscriptionInfo> createRepeated() => $pb.PbList<SubscriptionInfo>();\n  @$core.pragma('dart2js:noInline')\n  static SubscriptionInfo getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SubscriptionInfo>(create);\n  static SubscriptionInfo? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $fixnum.Int64 get upload => $_getI64(0);\n  @$pb.TagNumber(1)\n  set upload($fixnum.Int64 v) { $_setInt64(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasUpload() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearUpload() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $fixnum.Int64 get download => $_getI64(1);\n  @$pb.TagNumber(2)\n  set download($fixnum.Int64 v) { $_setInt64(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasDownload() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearDownload() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $fixnum.Int64 get total => $_getI64(2);\n  @$pb.TagNumber(3)\n  set total($fixnum.Int64 v) { $_setInt64(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasTotal() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearTotal() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $fixnum.Int64 get expire => $_getI64(3);\n  @$pb.TagNumber(4)\n  set expire($fixnum.Int64 v) { $_setInt64(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasExpire() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearExpire() => clearField(4);\n\n  @$pb.TagNumber(5)\n  $core.String get webPageUrl => $_getSZ(4);\n  @$pb.TagNumber(5)\n  set webPageUrl($core.String v) { $_setString(4, v); }\n  @$pb.TagNumber(5)\n  $core.bool hasWebPageUrl() => $_has(4);\n  @$pb.TagNumber(5)\n  void clearWebPageUrl() => clearField(5);\n\n  @$pb.TagNumber(6)\n  $core.String get supportUrl => $_getSZ(5);\n  @$pb.TagNumber(6)\n  set supportUrl($core.String v) { $_setString(5, v); }\n  @$pb.TagNumber(6)\n  $core.bool hasSupportUrl() => $_has(5);\n  @$pb.TagNumber(6)\n  void clearSupportUrl() => clearField(6);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/profile/profile.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/profile/profile.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/profile/profile.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/profile/profile.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n@$core.Deprecated('Use profileEntityDescriptor instead')\nconst ProfileEntity$json = const {\n  '1': 'ProfileEntity',\n  '2': const [\n    const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},\n    const {'1': 'name', '3': 3, '4': 1, '5': 9, '10': 'name'},\n    const {'1': 'url', '3': 4, '4': 1, '5': 9, '10': 'url'},\n    const {'1': 'last_update', '3': 5, '4': 1, '5': 3, '10': 'lastUpdate'},\n    const {'1': 'options', '3': 6, '4': 1, '5': 11, '6': '.profile.ProfileOptions', '10': 'options'},\n    const {'1': 'sub_info', '3': 7, '4': 1, '5': 11, '6': '.profile.SubscriptionInfo', '10': 'subInfo'},\n    const {'1': 'override_hiddify_options', '3': 8, '4': 1, '5': 11, '6': '.hiddifyoptions.HiddifyOptions', '10': 'overrideHiddifyOptions'},\n  ],\n};\n\n/// Descriptor for `ProfileEntity`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List profileEntityDescriptor = $convert.base64Decode('Cg1Qcm9maWxlRW50aXR5Eg4KAmlkGAEgASgJUgJpZBISCgRuYW1lGAMgASgJUgRuYW1lEhAKA3VybBgEIAEoCVIDdXJsEh8KC2xhc3RfdXBkYXRlGAUgASgDUgpsYXN0VXBkYXRlEjEKB29wdGlvbnMYBiABKAsyFy5wcm9maWxlLlByb2ZpbGVPcHRpb25zUgdvcHRpb25zEjQKCHN1Yl9pbmZvGAcgASgLMhkucHJvZmlsZS5TdWJzY3JpcHRpb25JbmZvUgdzdWJJbmZvElgKGG92ZXJyaWRlX2hpZGRpZnlfb3B0aW9ucxgIIAEoCzIeLmhpZGRpZnlvcHRpb25zLkhpZGRpZnlPcHRpb25zUhZvdmVycmlkZUhpZGRpZnlPcHRpb25z');\n@$core.Deprecated('Use profileOptionsDescriptor instead')\nconst ProfileOptions$json = const {\n  '1': 'ProfileOptions',\n  '2': const [\n    const {'1': 'update_interval', '3': 1, '4': 1, '5': 3, '10': 'updateInterval'},\n  ],\n};\n\n/// Descriptor for `ProfileOptions`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List profileOptionsDescriptor = $convert.base64Decode('Cg5Qcm9maWxlT3B0aW9ucxInCg91cGRhdGVfaW50ZXJ2YWwYASABKANSDnVwZGF0ZUludGVydmFs');\n@$core.Deprecated('Use subscriptionInfoDescriptor instead')\nconst SubscriptionInfo$json = const {\n  '1': 'SubscriptionInfo',\n  '2': const [\n    const {'1': 'upload', '3': 1, '4': 1, '5': 3, '10': 'upload'},\n    const {'1': 'download', '3': 2, '4': 1, '5': 3, '10': 'download'},\n    const {'1': 'total', '3': 3, '4': 1, '5': 3, '10': 'total'},\n    const {'1': 'expire', '3': 4, '4': 1, '5': 3, '10': 'expire'},\n    const {'1': 'web_page_url', '3': 5, '4': 1, '5': 9, '10': 'webPageUrl'},\n    const {'1': 'support_url', '3': 6, '4': 1, '5': 9, '10': 'supportUrl'},\n  ],\n};\n\n/// Descriptor for `SubscriptionInfo`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List subscriptionInfoDescriptor = $convert.base64Decode('ChBTdWJzY3JpcHRpb25JbmZvEhYKBnVwbG9hZBgBIAEoA1IGdXBsb2FkEhoKCGRvd25sb2FkGAIgASgDUghkb3dubG9hZBIUCgV0b3RhbBgDIAEoA1IFdG90YWwSFgoGZXhwaXJlGAQgASgDUgZleHBpcmUSIAoMd2ViX3BhZ2VfdXJsGAUgASgJUgp3ZWJQYWdlVXJsEh8KC3N1cHBvcnRfdXJsGAYgASgJUgpzdXBwb3J0VXJs');\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/profile/profile_service.pb.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/profile/profile_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\n\nimport 'package:protobuf/protobuf.dart' as $pb;\n\nimport 'profile.pb.dart' as $4;\n\nimport '../hcommon/common.pbenum.dart' as $1;\n\nclass ProfileRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ProfileRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'profile'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'url')\n    ..hasRequiredFields = false\n  ;\n\n  ProfileRequest._() : super();\n  factory ProfileRequest({\n    $core.String? id,\n    $core.String? name,\n    $core.String? url,\n  }) {\n    final _result = create();\n    if (id != null) {\n      _result.id = id;\n    }\n    if (name != null) {\n      _result.name = name;\n    }\n    if (url != null) {\n      _result.url = url;\n    }\n    return _result;\n  }\n  factory ProfileRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ProfileRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ProfileRequest clone() => ProfileRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ProfileRequest copyWith(void Function(ProfileRequest) updates) => super.copyWith((message) => updates(message as ProfileRequest)) as ProfileRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ProfileRequest create() => ProfileRequest._();\n  ProfileRequest createEmptyInstance() => create();\n  static $pb.PbList<ProfileRequest> createRepeated() => $pb.PbList<ProfileRequest>();\n  @$core.pragma('dart2js:noInline')\n  static ProfileRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ProfileRequest>(create);\n  static ProfileRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get id => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set id($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasId() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearId() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get name => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set name($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasName() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearName() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get url => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set url($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasUrl() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearUrl() => clearField(3);\n}\n\nclass AddProfileRequest extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'AddProfileRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'profile'), createEmptyInstance: create)\n    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'url')\n    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'content')\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')\n    ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'markAsActive')\n    ..hasRequiredFields = false\n  ;\n\n  AddProfileRequest._() : super();\n  factory AddProfileRequest({\n    $core.String? url,\n    $core.String? content,\n    $core.String? name,\n    $core.bool? markAsActive,\n  }) {\n    final _result = create();\n    if (url != null) {\n      _result.url = url;\n    }\n    if (content != null) {\n      _result.content = content;\n    }\n    if (name != null) {\n      _result.name = name;\n    }\n    if (markAsActive != null) {\n      _result.markAsActive = markAsActive;\n    }\n    return _result;\n  }\n  factory AddProfileRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory AddProfileRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  AddProfileRequest clone() => AddProfileRequest()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  AddProfileRequest copyWith(void Function(AddProfileRequest) updates) => super.copyWith((message) => updates(message as AddProfileRequest)) as AddProfileRequest; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static AddProfileRequest create() => AddProfileRequest._();\n  AddProfileRequest createEmptyInstance() => create();\n  static $pb.PbList<AddProfileRequest> createRepeated() => $pb.PbList<AddProfileRequest>();\n  @$core.pragma('dart2js:noInline')\n  static AddProfileRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AddProfileRequest>(create);\n  static AddProfileRequest? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.String get url => $_getSZ(0);\n  @$pb.TagNumber(1)\n  set url($core.String v) { $_setString(0, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasUrl() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearUrl() => clearField(1);\n\n  @$pb.TagNumber(2)\n  $core.String get content => $_getSZ(1);\n  @$pb.TagNumber(2)\n  set content($core.String v) { $_setString(1, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasContent() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearContent() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get name => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set name($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasName() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearName() => clearField(3);\n\n  @$pb.TagNumber(4)\n  $core.bool get markAsActive => $_getBF(3);\n  @$pb.TagNumber(4)\n  set markAsActive($core.bool v) { $_setBool(3, v); }\n  @$pb.TagNumber(4)\n  $core.bool hasMarkAsActive() => $_has(3);\n  @$pb.TagNumber(4)\n  void clearMarkAsActive() => clearField(4);\n}\n\nclass ProfileResponse extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ProfileResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'profile'), createEmptyInstance: create)\n    ..aOM<$4.ProfileEntity>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'profile', subBuilder: $4.ProfileEntity.create)\n    ..e<$1.ResponseCode>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'responseCode', $pb.PbFieldType.OE, defaultOrMaker: $1.ResponseCode.OK, valueOf: $1.ResponseCode.valueOf, enumValues: $1.ResponseCode.values)\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message')\n    ..hasRequiredFields = false\n  ;\n\n  ProfileResponse._() : super();\n  factory ProfileResponse({\n    $4.ProfileEntity? profile,\n    $1.ResponseCode? responseCode,\n    $core.String? message,\n  }) {\n    final _result = create();\n    if (profile != null) {\n      _result.profile = profile;\n    }\n    if (responseCode != null) {\n      _result.responseCode = responseCode;\n    }\n    if (message != null) {\n      _result.message = message;\n    }\n    return _result;\n  }\n  factory ProfileResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory ProfileResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  ProfileResponse clone() => ProfileResponse()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  ProfileResponse copyWith(void Function(ProfileResponse) updates) => super.copyWith((message) => updates(message as ProfileResponse)) as ProfileResponse; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static ProfileResponse create() => ProfileResponse._();\n  ProfileResponse createEmptyInstance() => create();\n  static $pb.PbList<ProfileResponse> createRepeated() => $pb.PbList<ProfileResponse>();\n  @$core.pragma('dart2js:noInline')\n  static ProfileResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ProfileResponse>(create);\n  static ProfileResponse? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $4.ProfileEntity get profile => $_getN(0);\n  @$pb.TagNumber(1)\n  set profile($4.ProfileEntity v) { setField(1, v); }\n  @$pb.TagNumber(1)\n  $core.bool hasProfile() => $_has(0);\n  @$pb.TagNumber(1)\n  void clearProfile() => clearField(1);\n  @$pb.TagNumber(1)\n  $4.ProfileEntity ensureProfile() => $_ensure(0);\n\n  @$pb.TagNumber(2)\n  $1.ResponseCode get responseCode => $_getN(1);\n  @$pb.TagNumber(2)\n  set responseCode($1.ResponseCode v) { setField(2, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasResponseCode() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearResponseCode() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get message => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set message($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasMessage() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearMessage() => clearField(3);\n}\n\nclass MultiProfilesResponse extends $pb.GeneratedMessage {\n  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'MultiProfilesResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'profile'), createEmptyInstance: create)\n    ..pc<$4.ProfileEntity>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'profiles', $pb.PbFieldType.PM, subBuilder: $4.ProfileEntity.create)\n    ..e<$1.ResponseCode>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'responseCode', $pb.PbFieldType.OE, defaultOrMaker: $1.ResponseCode.OK, valueOf: $1.ResponseCode.valueOf, enumValues: $1.ResponseCode.values)\n    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message')\n    ..hasRequiredFields = false\n  ;\n\n  MultiProfilesResponse._() : super();\n  factory MultiProfilesResponse({\n    $core.Iterable<$4.ProfileEntity>? profiles,\n    $1.ResponseCode? responseCode,\n    $core.String? message,\n  }) {\n    final _result = create();\n    if (profiles != null) {\n      _result.profiles.addAll(profiles);\n    }\n    if (responseCode != null) {\n      _result.responseCode = responseCode;\n    }\n    if (message != null) {\n      _result.message = message;\n    }\n    return _result;\n  }\n  factory MultiProfilesResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);\n  factory MultiProfilesResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '\n  'Will be removed in next major version')\n  MultiProfilesResponse clone() => MultiProfilesResponse()..mergeFromMessage(this);\n  @$core.Deprecated(\n  'Using this can add significant overhead to your binary. '\n  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '\n  'Will be removed in next major version')\n  MultiProfilesResponse copyWith(void Function(MultiProfilesResponse) updates) => super.copyWith((message) => updates(message as MultiProfilesResponse)) as MultiProfilesResponse; // ignore: deprecated_member_use\n  $pb.BuilderInfo get info_ => _i;\n  @$core.pragma('dart2js:noInline')\n  static MultiProfilesResponse create() => MultiProfilesResponse._();\n  MultiProfilesResponse createEmptyInstance() => create();\n  static $pb.PbList<MultiProfilesResponse> createRepeated() => $pb.PbList<MultiProfilesResponse>();\n  @$core.pragma('dart2js:noInline')\n  static MultiProfilesResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MultiProfilesResponse>(create);\n  static MultiProfilesResponse? _defaultInstance;\n\n  @$pb.TagNumber(1)\n  $core.List<$4.ProfileEntity> get profiles => $_getList(0);\n\n  @$pb.TagNumber(2)\n  $1.ResponseCode get responseCode => $_getN(1);\n  @$pb.TagNumber(2)\n  set responseCode($1.ResponseCode v) { setField(2, v); }\n  @$pb.TagNumber(2)\n  $core.bool hasResponseCode() => $_has(1);\n  @$pb.TagNumber(2)\n  void clearResponseCode() => clearField(2);\n\n  @$pb.TagNumber(3)\n  $core.String get message => $_getSZ(2);\n  @$pb.TagNumber(3)\n  set message($core.String v) { $_setString(2, v); }\n  @$pb.TagNumber(3)\n  $core.bool hasMessage() => $_has(2);\n  @$pb.TagNumber(3)\n  void clearMessage() => clearField(3);\n}\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/profile/profile_service.pbenum.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/profile/profile_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/profile/profile_service.pbgrpc.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/profile/profile_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:async' as $async;\n\nimport 'dart:core' as $core;\n\nimport 'package:grpc/service_api.dart' as $grpc;\nimport 'profile_service.pb.dart' as $3;\nimport 'profile.pb.dart' as $4;\nimport '../hcommon/common.pb.dart' as $1;\nexport 'profile_service.pb.dart';\n\nclass ProfileServiceClient extends $grpc.Client {\n  static final _$getProfile =\n      $grpc.ClientMethod<$3.ProfileRequest, $3.ProfileResponse>(\n          '/profile.ProfileService/GetProfile',\n          ($3.ProfileRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $3.ProfileResponse.fromBuffer(value));\n  static final _$updateProfile =\n      $grpc.ClientMethod<$4.ProfileEntity, $3.ProfileResponse>(\n          '/profile.ProfileService/UpdateProfile',\n          ($4.ProfileEntity value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $3.ProfileResponse.fromBuffer(value));\n  static final _$getAllProfiles =\n      $grpc.ClientMethod<$1.Empty, $3.MultiProfilesResponse>(\n          '/profile.ProfileService/GetAllProfiles',\n          ($1.Empty value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $3.MultiProfilesResponse.fromBuffer(value));\n  static final _$getActiveProfile =\n      $grpc.ClientMethod<$1.Empty, $3.ProfileResponse>(\n          '/profile.ProfileService/GetActiveProfile',\n          ($1.Empty value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $3.ProfileResponse.fromBuffer(value));\n  static final _$setActiveProfile =\n      $grpc.ClientMethod<$3.ProfileRequest, $1.Response>(\n          '/profile.ProfileService/SetActiveProfile',\n          ($3.ProfileRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) => $1.Response.fromBuffer(value));\n  static final _$addProfile =\n      $grpc.ClientMethod<$3.AddProfileRequest, $3.ProfileResponse>(\n          '/profile.ProfileService/AddProfile',\n          ($3.AddProfileRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) =>\n              $3.ProfileResponse.fromBuffer(value));\n  static final _$deleteProfile =\n      $grpc.ClientMethod<$3.ProfileRequest, $1.Response>(\n          '/profile.ProfileService/DeleteProfile',\n          ($3.ProfileRequest value) => value.writeToBuffer(),\n          ($core.List<$core.int> value) => $1.Response.fromBuffer(value));\n\n  ProfileServiceClient($grpc.ClientChannel channel,\n      {$grpc.CallOptions? options,\n      $core.Iterable<$grpc.ClientInterceptor>? interceptors})\n      : super(channel, options: options, interceptors: interceptors);\n\n  $grpc.ResponseFuture<$3.ProfileResponse> getProfile($3.ProfileRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$getProfile, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$3.ProfileResponse> updateProfile(\n      $4.ProfileEntity request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$updateProfile, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$3.MultiProfilesResponse> getAllProfiles(\n      $1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$getAllProfiles, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$3.ProfileResponse> getActiveProfile($1.Empty request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$getActiveProfile, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$1.Response> setActiveProfile($3.ProfileRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$setActiveProfile, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$3.ProfileResponse> addProfile(\n      $3.AddProfileRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$addProfile, request, options: options);\n  }\n\n  $grpc.ResponseFuture<$1.Response> deleteProfile($3.ProfileRequest request,\n      {$grpc.CallOptions? options}) {\n    return $createUnaryCall(_$deleteProfile, request, options: options);\n  }\n}\n\nabstract class ProfileServiceBase extends $grpc.Service {\n  $core.String get $name => 'profile.ProfileService';\n\n  ProfileServiceBase() {\n    $addMethod($grpc.ServiceMethod<$3.ProfileRequest, $3.ProfileResponse>(\n        'GetProfile',\n        getProfile_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $3.ProfileRequest.fromBuffer(value),\n        ($3.ProfileResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$4.ProfileEntity, $3.ProfileResponse>(\n        'UpdateProfile',\n        updateProfile_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $4.ProfileEntity.fromBuffer(value),\n        ($3.ProfileResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $3.MultiProfilesResponse>(\n        'GetAllProfiles',\n        getAllProfiles_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($3.MultiProfilesResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$1.Empty, $3.ProfileResponse>(\n        'GetActiveProfile',\n        getActiveProfile_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $1.Empty.fromBuffer(value),\n        ($3.ProfileResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$3.ProfileRequest, $1.Response>(\n        'SetActiveProfile',\n        setActiveProfile_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $3.ProfileRequest.fromBuffer(value),\n        ($1.Response value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$3.AddProfileRequest, $3.ProfileResponse>(\n        'AddProfile',\n        addProfile_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $3.AddProfileRequest.fromBuffer(value),\n        ($3.ProfileResponse value) => value.writeToBuffer()));\n    $addMethod($grpc.ServiceMethod<$3.ProfileRequest, $1.Response>(\n        'DeleteProfile',\n        deleteProfile_Pre,\n        false,\n        false,\n        ($core.List<$core.int> value) => $3.ProfileRequest.fromBuffer(value),\n        ($1.Response value) => value.writeToBuffer()));\n  }\n\n  $async.Future<$3.ProfileResponse> getProfile_Pre(\n      $grpc.ServiceCall call, $async.Future<$3.ProfileRequest> request) async {\n    return getProfile(call, await request);\n  }\n\n  $async.Future<$3.ProfileResponse> updateProfile_Pre(\n      $grpc.ServiceCall call, $async.Future<$4.ProfileEntity> request) async {\n    return updateProfile(call, await request);\n  }\n\n  $async.Future<$3.MultiProfilesResponse> getAllProfiles_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async {\n    return getAllProfiles(call, await request);\n  }\n\n  $async.Future<$3.ProfileResponse> getActiveProfile_Pre(\n      $grpc.ServiceCall call, $async.Future<$1.Empty> request) async {\n    return getActiveProfile(call, await request);\n  }\n\n  $async.Future<$1.Response> setActiveProfile_Pre(\n      $grpc.ServiceCall call, $async.Future<$3.ProfileRequest> request) async {\n    return setActiveProfile(call, await request);\n  }\n\n  $async.Future<$3.ProfileResponse> addProfile_Pre($grpc.ServiceCall call,\n      $async.Future<$3.AddProfileRequest> request) async {\n    return addProfile(call, await request);\n  }\n\n  $async.Future<$1.Response> deleteProfile_Pre(\n      $grpc.ServiceCall call, $async.Future<$3.ProfileRequest> request) async {\n    return deleteProfile(call, await request);\n  }\n\n  $async.Future<$3.ProfileResponse> getProfile(\n      $grpc.ServiceCall call, $3.ProfileRequest request);\n  $async.Future<$3.ProfileResponse> updateProfile(\n      $grpc.ServiceCall call, $4.ProfileEntity request);\n  $async.Future<$3.MultiProfilesResponse> getAllProfiles(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Future<$3.ProfileResponse> getActiveProfile(\n      $grpc.ServiceCall call, $1.Empty request);\n  $async.Future<$1.Response> setActiveProfile(\n      $grpc.ServiceCall call, $3.ProfileRequest request);\n  $async.Future<$3.ProfileResponse> addProfile(\n      $grpc.ServiceCall call, $3.AddProfileRequest request);\n  $async.Future<$1.Response> deleteProfile(\n      $grpc.ServiceCall call, $3.ProfileRequest request);\n}\n"
  },
  {
    "path": "lib/hiddifycore/generated/v2/profile/profile_service.pbjson.dart",
    "content": "///\n//  Generated code. Do not modify.\n//  source: v2/profile/profile_service.proto\n//\n// @dart = 2.12\n// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name\n\nimport 'dart:core' as $core;\nimport 'dart:convert' as $convert;\nimport 'dart:typed_data' as $typed_data;\n@$core.Deprecated('Use profileRequestDescriptor instead')\nconst ProfileRequest$json = const {\n  '1': 'ProfileRequest',\n  '2': const [\n    const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},\n    const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'},\n    const {'1': 'url', '3': 3, '4': 1, '5': 9, '10': 'url'},\n  ],\n};\n\n/// Descriptor for `ProfileRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List profileRequestDescriptor = $convert.base64Decode('Cg5Qcm9maWxlUmVxdWVzdBIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRIQCgN1cmwYAyABKAlSA3VybA==');\n@$core.Deprecated('Use addProfileRequestDescriptor instead')\nconst AddProfileRequest$json = const {\n  '1': 'AddProfileRequest',\n  '2': const [\n    const {'1': 'url', '3': 1, '4': 1, '5': 9, '10': 'url'},\n    const {'1': 'content', '3': 2, '4': 1, '5': 9, '10': 'content'},\n    const {'1': 'name', '3': 3, '4': 1, '5': 9, '10': 'name'},\n    const {'1': 'mark_as_active', '3': 4, '4': 1, '5': 8, '10': 'markAsActive'},\n  ],\n};\n\n/// Descriptor for `AddProfileRequest`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List addProfileRequestDescriptor = $convert.base64Decode('ChFBZGRQcm9maWxlUmVxdWVzdBIQCgN1cmwYASABKAlSA3VybBIYCgdjb250ZW50GAIgASgJUgdjb250ZW50EhIKBG5hbWUYAyABKAlSBG5hbWUSJAoObWFya19hc19hY3RpdmUYBCABKAhSDG1hcmtBc0FjdGl2ZQ==');\n@$core.Deprecated('Use profileResponseDescriptor instead')\nconst ProfileResponse$json = const {\n  '1': 'ProfileResponse',\n  '2': const [\n    const {'1': 'profile', '3': 1, '4': 1, '5': 11, '6': '.profile.ProfileEntity', '10': 'profile'},\n    const {'1': 'response_code', '3': 2, '4': 1, '5': 14, '6': '.hcommon.ResponseCode', '10': 'responseCode'},\n    const {'1': 'message', '3': 3, '4': 1, '5': 9, '10': 'message'},\n  ],\n};\n\n/// Descriptor for `ProfileResponse`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List profileResponseDescriptor = $convert.base64Decode('Cg9Qcm9maWxlUmVzcG9uc2USMAoHcHJvZmlsZRgBIAEoCzIWLnByb2ZpbGUuUHJvZmlsZUVudGl0eVIHcHJvZmlsZRI6Cg1yZXNwb25zZV9jb2RlGAIgASgOMhUuaGNvbW1vbi5SZXNwb25zZUNvZGVSDHJlc3BvbnNlQ29kZRIYCgdtZXNzYWdlGAMgASgJUgdtZXNzYWdl');\n@$core.Deprecated('Use multiProfilesResponseDescriptor instead')\nconst MultiProfilesResponse$json = const {\n  '1': 'MultiProfilesResponse',\n  '2': const [\n    const {'1': 'profiles', '3': 1, '4': 3, '5': 11, '6': '.profile.ProfileEntity', '10': 'profiles'},\n    const {'1': 'response_code', '3': 2, '4': 1, '5': 14, '6': '.hcommon.ResponseCode', '10': 'responseCode'},\n    const {'1': 'message', '3': 3, '4': 1, '5': 9, '10': 'message'},\n  ],\n};\n\n/// Descriptor for `MultiProfilesResponse`. Decode as a `google.protobuf.DescriptorProto`.\nfinal $typed_data.Uint8List multiProfilesResponseDescriptor = $convert.base64Decode('ChVNdWx0aVByb2ZpbGVzUmVzcG9uc2USMgoIcHJvZmlsZXMYASADKAsyFi5wcm9maWxlLlByb2ZpbGVFbnRpdHlSCHByb2ZpbGVzEjoKDXJlc3BvbnNlX2NvZGUYAiABKA4yFS5oY29tbW9uLlJlc3BvbnNlQ29kZVIMcmVzcG9uc2VDb2RlEhgKB21lc3NhZ2UYAyABKAlSB21lc3NhZ2U=');\n"
  },
  {
    "path": "lib/hiddifycore/hiddify_core_service.dart",
    "content": "import 'dart:async';\nimport 'dart:convert';\nimport 'dart:math';\n\nimport 'package:fpdart/fpdart.dart';\nimport 'package:grpc/grpc.dart';\nimport 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/core/model/directories.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/features/connection/model/connection_failure.dart';\nimport 'package:hiddify/features/settings/data/config_option_repository.dart';\nimport 'package:hiddify/hiddifycore/core_interface/core_interface.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcommon/common.pb.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore_service.pbgrpc.dart';\nimport 'package:hiddify/hiddifycore/init_signal.dart';\nimport 'package:hiddify/singbox/model/singbox_config_option.dart';\nimport 'package:hiddify/features/log/model/log_level.dart' as config_log_level;\nimport 'package:hiddify/singbox/model/core_status.dart';\nimport 'package:hiddify/singbox/model/warp_account.dart';\n\nimport 'package:hiddify/hiddifycore/core_interface/core_interface_wrapper_stub.dart'\n    if (dart.library.io) 'package:hiddify/hiddifycore/core_interface/core_interface_wrapper.dart';\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:hiddify/utils/platform_utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:loggy/loggy.dart' as loggyl;\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:rxdart/rxdart.dart';\n\nclass HiddifyCoreService with InfraLogger {\n  HiddifyCoreService(this.ref);\n  final Ref ref;\n\n  // CoreHiddifyCoreService() {}\n  final core = getCoreInterface();\n\n  CoreStatus currentState = const CoreStatus.stopped();\n  final statusController = BehaviorSubject<CoreStatus>();\n  final logController = BehaviorSubject<List<LogMessage>>();\n  final CallOptions? grpcOptions = null; //CallOptions(timeout: const Duration(milliseconds: 10000));\n  final Map<String, StreamSubscription?> subscriptions = {};\n  List<OutboundGroup> latest = [];\n\n  Future<void> init() async {\n    await setup()\n        .mapLeft((e) {\n          loggy.error(e);\n          if (PlatformUtils.isIOS) return;\n          statusController.add(const CoreStatus.stopped());\n          ref.read(inAppNotificationControllerProvider).showErrorToast(e);\n        })\n        .map((_) {\n          loggy.info(\"Hiddify-core setup done\");\n          ref.read(coreRestartSignalProvider.notifier).restart();\n        })\n        .run();\n  }\n\n  /// validates config by path and save it\n  ///\n  /// [path] is used to save validated config\n  /// [tempPath] includes base config, possibly invalid\n  /// [debug] indicates if debug mode (avoid in prod)\n\n  TaskEither<String, Unit> validateConfigByPath(String path, String tempPath, bool debug) {\n    return TaskEither(() async {\n      try {\n        final response = await core.fgClient.parse(ParseRequest(tempPath: tempPath, configPath: path, debug: false));\n        if (response.responseCode != ResponseCode.OK) return left(\"${response.responseCode} ${response.message}\");\n      } catch (e) {\n        await setup().run();\n        final response = await core.fgClient.parse(ParseRequest(tempPath: tempPath, configPath: path, debug: false));\n        if (response.responseCode != ResponseCode.OK) return left(\"${response.responseCode} ${response.message}\");\n      }\n      return right(unit);\n    });\n  }\n\n  TaskEither<String, String> generateFullConfigByPath(String path) {\n    return TaskEither(() async {\n      final response = await core.fgClient.parse(ParseRequest(configPath: path, debug: false));\n      if (response.responseCode != ResponseCode.OK) return left(\"${response.responseCode} ${response.message}\");\n      return right(response.content);\n    });\n  }\n\n  TaskEither<String, Unit> setup() {\n    return TaskEither(() async {\n      try {\n        final directories = ref.read(appDirectoriesProvider).requireValue;\n        final debug = ref.read(debugModeNotifierProvider);\n        final setupResponse = await core.setup(directories, debug, 3);\n\n        if (setupResponse.isNotEmpty) {\n          return left(setupResponse);\n        }\n\n        await startListeningLogs(\"fg\", core.fgClient);\n        // await startListeningStatus(\"fg\", core.fgClient);\n        if (!core.isSingleChannel()) {\n          await startListeningLogs(\"bg\", core.bgClient);\n        }\n        statusController.add(currentState);\n        await startListeningStatus(\"bg\", core.bgClient);\n        // ref.read(coreRestartSignalProvider.notifier).restart();\n        return right(unit);\n      } catch (e) {\n        return left(e.toString());\n      }\n    });\n  }\n\n  TaskEither<String, Unit> changeOptions(SingboxConfigOption options) {\n    return TaskEither(() async {\n      loggy.debug(\"changing options\");\n      // latestOptions = options;\n      try {\n        final res = await core.fgClient.changeHiddifySettings(\n          ChangeHiddifySettingsRequest(hiddifySettingsJson: jsonEncode(options.toJson())),\n        );\n        if (res.messageType != MessageType.EMPTY) return left(\"${res.messageType} ${res.message}\");\n        await core.bgClient.changeHiddifySettings(\n          ChangeHiddifySettingsRequest(hiddifySettingsJson: jsonEncode(options.toJson())),\n        );\n      } on GrpcError catch (e) {\n        if (e.code == StatusCode.unavailable) {\n          loggy.debug(\"background core is not started yet! $e\");\n        } else {\n          rethrow;\n        }\n      }\n\n      return right(unit);\n    });\n  }\n\n  TaskEither<ConnectionFailure, Unit> start(String path, String name, bool disableMemoryLimit) {\n    return TaskEither(() async {\n      statusController.add(currentState = const CoreStatus.starting());\n      loggy.debug(\"starting\");\n      final background = await core.setupBackground(path, name);\n      if (background != const CoreStatus.started()) {\n        statusController.add(currentState = const CoreStatus.stopped());\n        return left(background.getCoreAlert() ?? const ConnectionFailure.unexpected(\"failed to start core\"));\n      }\n      if (!core.isSingleChannel()) {\n        await startListeningLogs(\"bg\", core.bgClient);\n        await startListeningStatus(\"bg\", core.bgClient);\n      }\n      // if (latestOptions != null) {\n      //   await core.bgClient.changeHiddifySettings(\n      //     ChangeHiddifySettingsRequest(\n      //       hiddifySettingsJson: jsonEncode(latestOptions!.toJson()),\n      //     ),\n      //   );\n      // }\n      // final content = await File(path).readAsString();\n      // loggy.debug(\"starting with content: $content\");\n      try {\n        final res = await core.bgClient.start(\n          StartRequest(\n            configPath: path,\n            configName: name,\n            // configContent: content,\n            disableMemoryLimit: disableMemoryLimit,\n          ),\n        );\n        ref.read(coreRestartSignalProvider.notifier).restart();\n        if (res.messageType != MessageType.ALREADY_STARTED && res.messageType != MessageType.EMPTY) {\n          final alert = res.message.contains(\"denied\") ? CoreAlert.requestVPNPermission : CoreAlert.startFailed;\n          currentState = CoreStatus.stopped(\n            alert: alert,\n            message: \"failed to start core ${res.messageType} ${res.message}\",\n          );\n\n          statusController.add(currentState);\n\n          return left(\n            currentState.getCoreAlert() ??\n                ConnectionFailure.unexpected(\"failed to start core ${res.messageType} ${res.message}\"),\n          );\n        }\n      } on GrpcError catch (e) {\n        loggy.error(\"failed to start bg core: $e\");\n        ref.read(coreRestartSignalProvider.notifier).restart();\n        if (e.code == StatusCode.unavailable) {\n          return left(const ConnectionFailure.unexpected(\"background core is not started yet!\"));\n        }\n        // throw InvalidConfig(e.message);\n        // throw DioException.connectionError(requestOptions: RequestOptions(), reason: e.codeName, error: e);\n\n        // throw DioException(requestOptions: RequestOptions(), error: e);\n        return left(const ConnectionFailure.unexpected(\"failed to start background core\"));\n      }\n\n      // if (res.messageType != MessageType.EMPTY) return left(res);\n\n      return right(unit);\n    });\n  }\n\n  TaskEither<String, Unit> stop() {\n    return TaskEither(() async {\n      loggy.debug(\"stopping\");\n      var errMsg = \"\";\n      try {\n        final res = await core.bgClient.stop(Empty());\n      } on GrpcError catch (e) {\n        if (e.code == StatusCode.unknown && !(e.message?.contains(\"HTTP/2\") ?? false)) {\n          errMsg = e.message ?? \"failed to stop core: $e\";\n\n          loggy.error(\"failed to stop bg core: $e\");\n        }\n      } catch (e) {\n        loggy.error(\"failed to stop bg core: $e\");\n        // left(\"failed to stop core: $e\");\n      }\n      if (!await core.stop()) {}\n      statusController.add(currentState = const CoreStatus.stopped());\n      if (errMsg.isNotEmpty) return left(errMsg);\n      return right(unit);\n    });\n  }\n\n  TaskEither<String, Unit> restart(String path, String name, bool disableMemoryLimit) {\n    return TaskEither(() async {\n      loggy.debug(\"restarting\");\n      // if (!await core.restart(path, name)) {\n      try {\n        final res = await core.bgClient.restart(\n          StartRequest(configPath: path, configName: name, disableMemoryLimit: disableMemoryLimit, delayStart: true),\n        );\n        if (res.messageType != MessageType.EMPTY) return left(\"${res.messageType} ${res.message}\");\n      } on GrpcError catch (e) {\n        loggy.error(\"failed to restart bg core: $e\");\n        if (e.code == StatusCode.unknown && !(e.message?.contains(\"HTTP/2 error\") ?? false)) {\n          return left(\"${e.message}\");\n        }\n      }\n\n      return right(unit);\n      // await stop().run();\n      // return await start(path, name, disableMemoryLimit).run();\n      // }\n      // if (!core.isSingleChannel()) {\n      //   await startListeningStatus(\"bg\", core.bgClient);\n      //   await startListeningLogs(\"bg\", core.bgClient);\n      // }\n      // return right(unit);\n    });\n  }\n\n  TaskEither<String, Unit> resetTunnel() {\n    return TaskEither(() async {\n      // only available on iOS (and macOS later)\n      if (!PlatformUtils.isIOS) {\n        throw UnimplementedError(\"reset tunnel function unavailable on platform\");\n      }\n\n      // loggy.debug(\"resetting tunnel\");\n      final res = await core.resetTunnel();\n      if (res) {\n        return right(unit);\n      }\n      return left(\"failed to reset tunnel\");\n    });\n  }\n\n  // Stream<List<OutboundGroup>> watchGroups() async* {\n  //   loggy.debug(\"watching groups\");\n  //   yield* core.bgClient.outboundsInfo(Empty()).map((event) => event.items);\n  //   // res?.cancel();\n  // }\n\n  Stream<OutboundGroup?> watchGroup() async* {\n    loggy.debug(\"watching group\");\n    // interrupt managed by core\n\n    if (!core.isInitialized()) {\n      loggy.debug(\"core is not initialized, returning empty group stream\");\n      return;\n    }\n    try {\n      yield* core.bgClient.outboundsInfo(Empty()).map((event) => event.items.isEmpty ? null : event.items.first);\n    } catch (e) {\n      loggy.error(\"error watching group: $e\");\n      rethrow;\n    }\n    // //emitting first event immediately\n    // yield* core.bgClient.outboundsInfo(Empty()).take(1).map((event) => event.items.isEmpty ? null : event.items.first);\n    // //emitting other event after every 4 seconds(latest event)\n    // yield* core.bgClient.outboundsInfo(Empty()).throttleTime(const Duration(seconds: 4), leading: false, trailing: true).map((event) => event.items.isEmpty ? null : event.items.first);\n  }\n\n  Stream<List<OutboundGroup>> watchActiveGroups() async* {\n    loggy.info(\"watching active groups\");\n\n    if (!core.isInitialized()) {\n      loggy.debug(\"core is not initialized, returning empty group stream\");\n      return;\n    }\n\n    try {\n      yield* core.bgClient\n          .mainOutboundsInfo(Empty())\n          .map((event) {\n            return latest = event.items;\n          })\n          .startWith(latest);\n    } catch (e) {\n      loggy.error(\"error watching active groups: $e\");\n      rethrow;\n    }\n  }\n\n  //\n  // Stream<SingboxStatus> watchStatus() => _status;\n\n  ResponseStream<SystemInfo> watchStats() {\n    loggy.debug(\"watching stats\");\n    try {\n      return core.bgClient.getSystemInfoStream(Empty());\n    } catch (e) {\n      loggy.error(\"error watching stats: $e\");\n      rethrow;\n    }\n  }\n\n  TaskEither<String, Unit> selectOutbound(String groupTag, String outboundTag) {\n    return TaskEither(() async {\n      loggy.debug(\"selecting outbound\");\n      try {\n        final res = await core.bgClient.selectOutbound(\n          SelectOutboundRequest(groupTag: groupTag, outboundTag: outboundTag),\n          options: CallOptions(timeout: const Duration(seconds: 1)),\n        );\n        if (res.code != ResponseCode.OK) return left(\"${res.code} ${res.message}\");\n\n        return right(unit);\n      } catch (e) {\n        loggy.error(\"error selecting outbound: $e\");\n        rethrow;\n      }\n    });\n  }\n\n  TaskEither<String, Unit> urlTest(String tag) {\n    return TaskEither(() async {\n      loggy.debug(\"url test\");\n      try {\n        final res = await core.bgClient.urlTest(UrlTestRequest(tag: tag));\n        if (res.code != ResponseCode.OK) return left(\"${res.code} ${res.message}\");\n\n        return right(unit);\n      } catch (e) {\n        loggy.error(\"error in url test: $e\");\n        rethrow;\n      }\n    });\n  }\n\n  List<LogMessage> logBuffer = [];\n\n  // SingboxConfigOption? latestOptions;\n\n  Stream<List<LogMessage>> watchLogs(String path) async* {\n    if (!core.isInitialized()) {\n      loggy.debug(\"core is not initialized, returning empty log stream\");\n      return;\n    }\n    await startListeningLogs(\"bg\", core.bgClient);\n    await startListeningLogs(\"fg\", core.fgClient);\n    try {\n      yield* logController.stream;\n    } catch (e) {\n      loggy.error(\"error watching logs: $e\");\n      rethrow;\n    }\n    // Stream<List<String>> logStream(CoreClient coreClient) {\n    //   return coreClient.logListener(Empty()).asBroadcastStream().map((event) => [event.message]).onErrorResume((error, stackTrace) {\n    //     loggy.debug('Error in $coreClient: $error, retrying...');\n    //     final delay = (currentState == const SingboxStatus.stopped()) ? 5 : 1;\n    //     return const Stream<List<String>>.empty().delay(Duration(seconds: delay)).concatWith([logStream(coreClient)]);\n    //   });\n    // }\n\n    // // Create streams for both fg and bg clients with retry logic\n    // final fgLogStream = logStream(core.fgClient);\n\n    // if (core.bgClient == core.fgClient) {\n    //   yield* fgLogStream;\n    //   return;\n    // }\n    // final bgLogStream = logStream(core.bgClient);\n    // yield* MergeStream([bgLogStream, fgLogStream]);\n  }\n\n  TaskEither<String, Unit> clearLogs() {\n    return TaskEither(() async {\n      loggy.debug(\"clearing logs\");\n      logBuffer.clear();\n      // final res = await core.bgClient(Empty());\n      // if (res.code != ResponseCode.OK) return left(\"${res.code} ${res.message}\");\n      return right(unit);\n    });\n  }\n\n  TaskEither<String, WarpResponse> generateWarpConfig({\n    required String licenseKey,\n    required String previousAccountId,\n    required String previousAccessToken,\n  }) {\n    return TaskEither(() async {\n      loggy.debug(\"generating warp config\");\n      final warpConfig = await core.fgClient.generateWarpConfig(\n        GenerateWarpConfigRequest(\n          licenseKey: licenseKey,\n          accountId: previousAccountId,\n          accessToken: previousAccessToken,\n        ),\n      );\n      // if (warpConfig.code != ResponseCode.OK) return left(\"${warpConfig.code} ${warpConfig.message}\");\n      final WarpResponse warp = (\n        log: warpConfig.log,\n        accountId: warpConfig.account.accountId,\n        accessToken: warpConfig.account.accessToken,\n        wireguardConfig: jsonEncode(warpConfig.config.toProto3Json()),\n      );\n      return right(warp);\n    });\n  }\n\n  Stream<CoreStatus> watchStatus() async* {\n    await startListeningStatus(\"bg\", core.bgClient);\n    yield* statusController.stream;\n    // .endWith(const CoreStatus.stopped());\n  }\n\n  Future<void> startListeningStatus(String key, CoreClient cc) async {\n    await listenSingle<CoreStatus>(\n      \"${key}StatusListener\",\n      () => cc\n          .coreInfoListener(Empty(), options: grpcOptions)\n          .doOnCancel(() {\n            loggy.error(\"status\", \"Canceld\");\n            if (currentState == const CoreStatus.started()) currentState = const CoreStatus.stopped();\n          })\n          .doOnData((event) {\n            loggy.debug(\"status\", event);\n            if (currentState == const CoreStatus.started()) currentState = const CoreStatus.stopped();\n          })\n          .doOnDone(() {\n            loggy.error(\"status\", \"done\");\n            if (currentState == const CoreStatus.started()) currentState = const CoreStatus.stopped();\n          })\n          .endWith(CoreInfoResponse(coreState: CoreStates.STOPPED))\n          .map((event) {\n            currentState = CoreStatus.fromCoreInfo(event);\n            statusController.add(currentState);\n            return currentState;\n          }),\n      // .endWith(const CoreStatus.stopped())\n      onError: (error) {\n        loggy.error(\"Stream error in ${key}StatusListener: $error\");\n\n        // currentState = const CoreStatus.stopped();\n        // statusController.add(currentState);\n\n        // startListeningStatus(key, cc);\n      },\n    );\n  }\n\n  Future<void> startListeningLogs(String key, CoreClient cc) async {\n    final logLevel = ref.read(ConfigOptions.logLevel);\n    final coreLogLevel = getCoreLogLevel(logLevel);\n    final listenKey = \"${key}LogListener\";\n    // await stopListenSingle(listenKey);\n    await listenSingle<LogMessage>(listenKey, () {\n      return cc.logListener(LogRequest(level: coreLogLevel), options: grpcOptions).map((event) {\n        // Handle incoming event\n        logBuffer.add(event);\n        if (logBuffer.length > 300) {\n          logBuffer.removeAt(0);\n        }\n        logController.add(logBuffer);\n        // loggy.log(getLogLevel(event.level), event.message);\n        event.message.split('\\n').forEach((line) {\n          loggy.log(getLogLevel(event.level), line);\n        });\n        return event;\n      });\n    });\n  }\n\n  Future<void> stopListenSingle(String key) async {\n    // Collect keys to remove first\n    final keysToRemove = subscriptions.entries\n        .where((entry) => entry.key.startsWith(key))\n        .map((entry) => entry.key)\n        .toList();\n\n    // Cancel and remove\n    for (final k in keysToRemove) {\n      final sub = subscriptions[k];\n      await sub?.cancel(); // cancel the subscription\n\n      subscriptions.remove(k);\n    }\n  }\n\n  Future<StreamSubscription<T>?> listenSingle<T>(\n    String key,\n    Stream<T> Function() stream, {\n    Function(dynamic error)? onError,\n  }) async {\n    if (subscriptions.containsKey(key)) {\n      // return subscriptions[key] as StreamSubscription<T>?;\n      await stopListenSingle(key);\n    }\n    subscriptions[key] = null;\n    subscriptions[key] = stream().listen(\n      (event) {\n        // loggy.debug(event);\n      },\n      cancelOnError: true,\n      onError: (error) {\n        loggy.log(loggyl.LogLevel.error, 'Stream error: $error');\n        onError?.call(error);\n        subscriptions[key]?.cancel();\n        subscriptions.remove(key);\n      },\n    );\n    return subscriptions[key] as StreamSubscription<T>?;\n  }\n\n  loggyl.LogLevel getLogLevel(LogLevel level) {\n    return switch (level) {\n      LogLevel.DEBUG => loggyl.LogLevel.debug,\n      LogLevel.INFO => loggyl.LogLevel.info,\n      LogLevel.WARNING => loggyl.LogLevel.warning,\n      LogLevel.ERROR => loggyl.LogLevel.error,\n      LogLevel.FATAL => loggyl.LogLevel.error,\n      _ => loggyl.LogLevel.info, // Default case\n    };\n  }\n\n  LogLevel getCoreLogLevel(config_log_level.LogLevel level) {\n    return switch (level) {\n      config_log_level.LogLevel.trace => LogLevel.TRACE,\n      config_log_level.LogLevel.debug => LogLevel.DEBUG,\n      config_log_level.LogLevel.info => LogLevel.INFO,\n      config_log_level.LogLevel.warn => LogLevel.WARNING,\n      config_log_level.LogLevel.error => LogLevel.ERROR,\n      config_log_level.LogLevel.fatal => LogLevel.FATAL,\n      config_log_level.LogLevel.panic => LogLevel.FATAL,\n      _ => LogLevel.INFO, // Default case\n    };\n  }\n\n  Future<void> closeFront() async {\n    if (!core.isInitialized()) {\n      return;\n    }\n    if (!core.isSingleChannel()) {\n      await stopListenSingle(\"fg\");\n      await stopListenSingle(\"bg\");\n      try {\n        await core.fgClient.close(CloseRequest(mode: SetupMode.GRPC_NORMAL_INSECURE));\n      } catch (e) {}\n      try {\n        await core.fgClient.close(CloseRequest(mode: SetupMode.GRPC_NORMAL));\n      } catch (e) {}\n    }\n  }\n}\n"
  },
  {
    "path": "lib/hiddifycore/hiddify_core_service_provider.dart",
    "content": "import 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\n\npart 'hiddify_core_service_provider.g.dart';\n\n@Riverpod(keepAlive: true, dependencies: [AppDirectories, DebugModeNotifier, inAppNotificationController])\nHiddifyCoreService hiddifyCoreService(Ref ref) {\n  return HiddifyCoreService(ref);\n}\n"
  },
  {
    "path": "lib/hiddifycore/init_signal.dart",
    "content": "import 'package:hiddify/core/directories/directories_provider.dart';\nimport 'package:hiddify/core/notification/in_app_notification_controller.dart';\nimport 'package:hiddify/core/preferences/general_preferences.dart';\nimport 'package:hiddify/hiddifycore/hiddify_core_service.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\npart 'init_signal.g.dart';\n\n@riverpod\nclass CoreRestartSignal extends _$CoreRestartSignal {\n  @override\n  int build() => 0;\n\n  void restart() => state++;\n}\n"
  },
  {
    "path": "lib/main.dart",
    "content": "import 'package:flutter/material.dart';\n\nimport 'package:flutter/services.dart';\nimport 'package:hiddify/bootstrap.dart';\nimport 'package:hiddify/core/model/environment.dart';\n\nFuture<void> main() async {\n  final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();\n  // final widgetsBinding = SentryWidgetsFlutterBinding.ensureInitialized();\n  // debugPaintSizeEnabled = true;\n\n  SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);\n  SystemChrome.setSystemUIOverlayStyle(\n    const SystemUiOverlayStyle(statusBarColor: Colors.transparent, systemNavigationBarColor: Colors.transparent),\n  );\n\n  return await lazyBootstrap(widgetsBinding, Environment.dev);\n}\n"
  },
  {
    "path": "lib/main_prod.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:hiddify/bootstrap.dart';\nimport 'package:hiddify/core/model/environment.dart';\n\nFuture<void> main() async {\n  final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();\n\n  SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);\n  SystemChrome.setSystemUIOverlayStyle(\n    const SystemUiOverlayStyle(statusBarColor: Colors.transparent, systemNavigationBarColor: Colors.transparent),\n  );\n\n  return await lazyBootstrap(widgetsBinding, Environment.prod);\n}\n"
  },
  {
    "path": "lib/riverpod_observer.dart",
    "content": "import 'dart:developer';\r\n\r\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\r\n\r\nclass RiverpodObserver extends ProviderObserver {\r\n  @override\r\n  void didAddProvider(ProviderBase<Object?> provider, Object? value, ProviderContainer container) {\r\n    log('didAddProvider : ${provider.name ?? provider.runtimeType} : $value');\r\n  }\r\n\r\n  @override\r\n  void didDisposeProvider(ProviderBase<Object?> provider, ProviderContainer container) {\r\n    log('didDisposeProvider : ${provider.name ?? provider.runtimeType}');\r\n  }\r\n\r\n  @override\r\n  void didUpdateProvider(\r\n    ProviderBase<Object?> provider,\r\n    Object? previousValue,\r\n    Object? newValue,\r\n    ProviderContainer container,\r\n  ) {\r\n    log('didUpdateProvider : ${provider.name ?? provider.runtimeType} : $previousValue -> $newValue');\r\n  }\r\n}\r\n"
  },
  {
    "path": "lib/singbox/model/core_status.dart",
    "content": "import 'package:dartx/dartx.dart';\nimport 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/features/connection/model/connection_failure.dart';\nimport 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';\n\npart 'core_status.freezed.dart';\n\n@freezed\nsealed class CoreStatus with _$CoreStatus {\n  const CoreStatus._();\n\n  const factory CoreStatus.stopped({CoreAlert? alert, String? message}) = CoreStopped;\n  const factory CoreStatus.starting() = CoreStarting;\n  const factory CoreStatus.started() = CoreStarted;\n  const factory CoreStatus.stopping() = CoreStopping;\n\n  factory CoreStatus.fromEvent(dynamic event) {\n    event = event as Map<String, dynamic>?;\n    switch (event?[\"status\"]) {\n      case \"Stopped\":\n        final alertstr = event?[\"alert\"] as String?;\n        var msgStr = event?[\"message\"] as String?;\n        var alert = CoreAlert.values.firstOrNullWhere((e) => alertstr?.toLowerCase() == e.name.toLowerCase());\n        if ((alert == null) && (alertstr ?? \"\") != \"\") {\n          msgStr = ((msgStr ?? \"\") != \"\") ? \"$alertstr: $msgStr\" : alertstr;\n          alert = CoreAlert.unknown;\n        }\n        return CoreStatus.stopped(alert: alert, message: msgStr);\n\n      case \"Starting\":\n        return const CoreStarting();\n      case \"Started\":\n        return const CoreStarted();\n      case \"Stopping\":\n        return const CoreStopping();\n      default:\n        throw Exception(\"unexpected status [$event]\");\n    }\n  }\n  factory CoreStatus.fromCoreInfo(CoreInfoResponse event) {\n    switch (event.coreState) {\n      case CoreStates.STOPPED:\n        final CoreAlert? alert = switch (event.messageType) {\n          MessageType.EMPTY => null,\n          MessageType.ERROR_READING_CONFIG => CoreAlert.emptyConfiguration,\n          MessageType.START_COMMAND_SERVER => CoreAlert.startCommandServer,\n          MessageType.CREATE_SERVICE => CoreAlert.createService,\n          MessageType.START_SERVICE => CoreAlert.startService,\n          MessageType.UNEXPECTED_ERROR => CoreAlert.startService,\n          MessageType.INSTANCE_NOT_STOPPED => CoreAlert.startService,\n          MessageType.INSTANCE_NOT_STARTED => CoreAlert.startService,\n          MessageType.INSTANCE_NOT_FOUND => CoreAlert.startService,\n          MessageType.ERROR_PARSING_CONFIG => CoreAlert.emptyConfiguration,\n          MessageType.ERROR_BUILDING_CONFIG => CoreAlert.emptyConfiguration,\n          MessageType.EMPTY_CONFIGURATION => CoreAlert.emptyConfiguration,\n          MessageType.ALREADY_STOPPED => CoreAlert.createService,\n          MessageType.ALREADY_STARTED => CoreAlert.startService,\n\n          // MessageType.REQUEST_VPN_PERMISSION => SingboxAlert.requestVPNPermission,\n          // MessageType.REQUEST_NOTIFICATION_PERMISSION => SingboxAlert.requestNotificationPermission,\n          _ => CoreAlert.emptyConfiguration, // Default case\n        };\n        return CoreStatus.stopped(alert: alert, message: event.message);\n      case CoreStates.STARTING:\n        return const CoreStarting();\n      case CoreStates.STARTED:\n        return const CoreStarted();\n      case CoreStates.STOPPING:\n        return const CoreStopping();\n      default:\n        throw Exception(\"unexpected status [$event]\");\n    }\n  }\n\n  ConnectionFailure? getCoreAlert() {\n    return switch (this) {\n      CoreStopped(alert: final alert, message: final message) when alert != null => switch (alert) {\n        CoreAlert.emptyConfiguration => ConnectionFailure.invalidConfig(message),\n\n        CoreAlert.requestNotificationPermission => ConnectionFailure.missingNotificationPermission(message),\n\n        CoreAlert.requestVPNPermission => ConnectionFailure.missingVpnPermission(message),\n\n        CoreAlert.startCommandServer ||\n        CoreAlert.createService ||\n        CoreAlert.startService ||\n        CoreAlert.alreadyStarted ||\n        CoreAlert.startFailed => ConnectionFailure.unexpected(\"${alert.name} - $message\"),\n\n        _ => null,\n      },\n\n      _ => null,\n    };\n  }\n}\n\nenum CoreAlert {\n  requestVPNPermission,\n  requestNotificationPermission,\n  emptyConfiguration,\n  startCommandServer,\n  createService,\n  startService,\n  alreadyStarted,\n  startFailed,\n  unknown,\n}\n"
  },
  {
    "path": "lib/singbox/model/singbox_config_enum.dart",
    "content": "import 'dart:io';\n\nimport 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/localization/translations.dart';\nimport 'package:hiddify/utils/platform_utils.dart';\n\n@JsonEnum(valueField: 'key')\nenum ServiceMode {\n  proxy(\"proxy\"),\n  systemProxy(\"system-proxy\"),\n  tun(\"vpn\")\n  // tunService(\"vpn-service\")\n  ;\n\n  const ServiceMode(this.key);\n\n  final String key;\n\n  static ServiceMode get defaultMode => PlatformUtils.isDesktop ? systemProxy : tun;\n\n  /// supported service mode based on platform, use this instead of [values] in UI\n  static List<ServiceMode> get choices {\n    if (Platform.isWindows || Platform.isLinux) {\n      return values;\n    } else if (Platform.isMacOS) {\n      return [proxy, systemProxy, tun];\n    }\n    // mobile\n    return [proxy, tun];\n  }\n\n  // bool get isExperimental => switch (this) {\n  //       tun => PlatformUtils.isDesktop,\n  //       tunService => PlatformUtils.isDesktop,\n  //       _ => false,\n  //     };\n\n  String present(TranslationsEn t) => switch (this) {\n    proxy => t.pages.settings.inbound.serviceModes.proxy,\n    systemProxy => t.pages.settings.inbound.serviceModes.systemProxy,\n    tun => t.pages.settings.inbound.serviceModes.tun,\n    // tunService => t.pages.settings.inbound.serviceModes.tunService,\n  };\n\n  String presentShort(TranslationsEn t) => switch (this) {\n    proxy => t.pages.settings.inbound.shortServiceModes.proxy,\n    systemProxy => t.pages.settings.inbound.shortServiceModes.systemProxy,\n    tun => t.pages.settings.inbound.shortServiceModes.tun,\n    // tunService => t.pages.settings.inbound.shortServiceModes.tunService,\n  };\n}\n\n@JsonEnum(valueField: 'key')\nenum BalancerStrategy {\n  roundRobin(\"round-robin\"),\n  consistentHash(\"consistent-hashing\"),\n  stickySession(\"sticky-sessions\");\n\n  const BalancerStrategy(this.key);\n\n  final String key;\n\n  String present(TranslationsEn t) => switch (this) {\n    roundRobin => t.pages.settings.routing.balancerStrategy.roundRobin,\n    consistentHash => t.pages.settings.routing.balancerStrategy.consistentHash,\n    stickySession => t.pages.settings.routing.balancerStrategy.stickySession,\n  };\n}\n\n@JsonEnum(valueField: 'key')\nenum IPv6Mode {\n  disable(\"ipv4_only\"),\n  enable(\"prefer_ipv4\"),\n  prefer(\"prefer_ipv6\"),\n  only(\"ipv6_only\");\n\n  const IPv6Mode(this.key);\n\n  final String key;\n\n  String present(TranslationsEn t) => switch (this) {\n    disable => t.pages.settings.routing.ipv6Modes.disable,\n    enable => t.pages.settings.routing.ipv6Modes.enable,\n    prefer => t.pages.settings.routing.ipv6Modes.prefer,\n    only => t.pages.settings.routing.ipv6Modes.only,\n  };\n}\n\n@JsonEnum(valueField: 'key')\nenum DomainStrategy {\n  auto(\"\"),\n  preferIpv6(\"prefer_ipv6\"),\n  preferIpv4(\"prefer_ipv4\"),\n  ipv4Only(\"ipv4_only\"),\n  ipv6Only(\"ipv6_only\");\n\n  const DomainStrategy(this.key);\n\n  final String key;\n\n  String present(TranslationsEn t) => switch (this) {\n    auto => t.pages.settings.dns.domainStrategy.auto,\n    preferIpv6 => t.pages.settings.dns.domainStrategy.preferIpv6,\n    preferIpv4 => t.pages.settings.dns.domainStrategy.preferIpv4,\n    ipv4Only => t.pages.settings.dns.domainStrategy.ipv4Only,\n    ipv6Only => t.pages.settings.dns.domainStrategy.ipv6Only,\n  };\n}\n\nenum TunImplementation {\n  mixed,\n  system,\n  gvisor;\n\n  String present(TranslationsEn t) => switch (this) {\n    mixed => t.pages.settings.inbound.tunImplementations.mixed,\n    system => t.pages.settings.inbound.tunImplementations.system,\n    gvisor => t.pages.settings.inbound.tunImplementations.gvisor,\n  };\n}\n\nenum MuxProtocol { h2mux, smux, yamux }\n\n@JsonEnum(valueField: 'key')\nenum WarpDetourMode {\n  proxyOverWarp(\"proxy_over_warp\"),\n  warpOverProxy(\"warp_over_proxy\");\n\n  const WarpDetourMode(this.key);\n\n  final String key;\n\n  String present(TranslationsEn t) => switch (this) {\n    proxyOverWarp => t.pages.settings.warp.detourModes.proxyOverWarp,\n    warpOverProxy => t.pages.settings.warp.detourModes.warpOverProxy,\n  };\n\n  String presentExplain(TranslationsEn t) => switch (this) {\n    proxyOverWarp => t.pages.settings.warp.detourModes.proxyOverWarpExplain,\n    warpOverProxy => t.pages.settings.warp.detourModes.warpOverProxyExplain,\n  };\n}\n"
  },
  {
    "path": "lib/singbox/model/singbox_config_option.dart",
    "content": "import 'dart:convert';\n\nimport 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/model/optional_range.dart';\nimport 'package:hiddify/core/utils/json_converters.dart';\nimport 'package:hiddify/features/log/model/log_level.dart';\nimport 'package:hiddify/singbox/model/singbox_config_enum.dart';\nimport 'package:hiddify/singbox/model/singbox_rule.dart';\n\npart 'singbox_config_option.freezed.dart';\npart 'singbox_config_option.g.dart';\n\n@freezed\nclass SingboxConfigOption with _$SingboxConfigOption {\n  const SingboxConfigOption._();\n\n  @JsonSerializable(fieldRename: FieldRename.kebab)\n  const factory SingboxConfigOption({\n    required String region,\n    required BalancerStrategy balancerStrategy,\n    required bool blockAds,\n    required bool useXrayCoreWhenPossible,\n    required bool executeConfigAsIs,\n    required LogLevel logLevel,\n    required bool resolveDestination,\n    required IPv6Mode ipv6Mode,\n    required String remoteDnsAddress,\n    required DomainStrategy remoteDnsDomainStrategy,\n    required String directDnsAddress,\n    required DomainStrategy directDnsDomainStrategy,\n    required int mixedPort,\n    required int tproxyPort,\n    required int directPort,\n    required int redirectPort,\n    required TunImplementation tunImplementation,\n    required int mtu,\n    required bool strictRoute,\n    required String connectionTestUrl,\n    @IntervalInSecondsConverter() required Duration urlTestInterval,\n    required bool enableClashApi,\n    required int clashApiPort,\n    required bool enableTun,\n    // required bool enableTunService,\n    required bool setSystemProxy,\n    required bool bypassLan,\n    required bool allowConnectionFromLan,\n    required bool enableFakeDns,\n    // required bool enableDnsRouting,\n    required bool independentDnsCache,\n    required List<SingboxRule> rules,\n    // required SingboxMuxOption mux,\n    required SingboxTlsTricks tlsTricks,\n    required SingboxWarpOption warp,\n    required SingboxWarpOption warp2,\n  }) = _SingboxConfigOption;\n\n  String format() {\n    const encoder = JsonEncoder.withIndent('  ');\n    return encoder.convert(toJson());\n  }\n\n  factory SingboxConfigOption.fromJson(Map<String, dynamic> json) => _$SingboxConfigOptionFromJson(json);\n}\n\n@freezed\nclass SingboxWarpOption with _$SingboxWarpOption {\n  @JsonSerializable(fieldRename: FieldRename.kebab)\n  const factory SingboxWarpOption({\n    required bool enable,\n    required WarpDetourMode mode,\n    required String wireguardConfig,\n    required String licenseKey,\n    required String accountId,\n    required String accessToken,\n    required String cleanIp,\n    required int cleanPort,\n    @OptionalRangeJsonConverter() required OptionalRange noise,\n    @OptionalRangeJsonConverter() required OptionalRange noiseSize,\n    @OptionalRangeJsonConverter() required OptionalRange noiseDelay,\n    @OptionalRangeJsonConverter() required String noiseMode,\n  }) = _SingboxWarpOption;\n\n  factory SingboxWarpOption.fromJson(Map<String, dynamic> json) => _$SingboxWarpOptionFromJson(json);\n}\n\n// @freezed\n// class SingboxMuxOption with _$SingboxMuxOption {\n//   @JsonSerializable(fieldRename: FieldRename.kebab)\n//   const factory SingboxMuxOption({\n//     required bool enable,\n//     required bool padding,\n//     required int maxStreams,\n//     required MuxProtocol protocol,\n//   }) = _SingboxMuxOption;\n\n//   factory SingboxMuxOption.fromJson(Map<String, dynamic> json) => _$SingboxMuxOptionFromJson(json);\n// }\n\n@freezed\nclass SingboxTlsTricks with _$SingboxTlsTricks {\n  @JsonSerializable(fieldRename: FieldRename.kebab)\n  const factory SingboxTlsTricks({\n    required bool enableFragment,\n    @OptionalRangeJsonConverter() required OptionalRange fragmentSize,\n    @OptionalRangeJsonConverter() required OptionalRange fragmentSleep,\n    required bool mixedSniCase,\n    required bool enablePadding,\n    @OptionalRangeJsonConverter() required OptionalRange paddingSize,\n  }) = _SingboxTlsTricks;\n\n  factory SingboxTlsTricks.fromJson(Map<String, dynamic> json) => _$SingboxTlsTricksFromJson(json);\n}\n"
  },
  {
    "path": "lib/singbox/model/singbox_outbound.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/singbox/model/singbox_proxy_type.dart';\n\npart 'singbox_outbound.freezed.dart';\npart 'singbox_outbound.g.dart';\n\n@freezed\nclass SingboxOutboundGroup with _$SingboxOutboundGroup {\n  @JsonSerializable(fieldRename: FieldRename.kebab)\n  const factory SingboxOutboundGroup({\n    required String tag,\n    @JsonKey(fromJson: _typeFromJson) required ProxyType type,\n    required String selected,\n    @Default([]) List<SingboxOutboundGroupItem> items,\n  }) = _SingboxOutboundGroup;\n\n  factory SingboxOutboundGroup.fromJson(Map<String, dynamic> json) => _$SingboxOutboundGroupFromJson(json);\n\n  // factory SingboxOutboundGroup.fromGrpc(OutboundGroup og) => _$SingboxOutboundGroup(tag=og.tag, type=_keyMap[og.type]!, selected=og.selected, items=og.items.map((e) => SingboxOutboundGroupItem.fromGRPC(e)).toList());\n}\n\n@freezed\nclass SingboxOutboundGroupItem with _$SingboxOutboundGroupItem {\n  const SingboxOutboundGroupItem._();\n\n  @JsonSerializable(fieldRename: FieldRename.kebab)\n  const factory SingboxOutboundGroupItem({required String tag, required String type, required int urlTestDelay}) =\n      _SingboxOutboundGroupItem;\n\n  factory SingboxOutboundGroupItem.fromJson(Map<String, dynamic> json) => _$SingboxOutboundGroupItemFromJson(json);\n}\n\nfinal Map<String, ProxyType> _keyMap = Map.fromEntries(ProxyType.values.map((e) => MapEntry(e.key, e)));\n\nProxyType _typeFromJson(dynamic type) => ProxyType.fromJson(type);\n"
  },
  {
    "path": "lib/singbox/model/singbox_proxy_type.dart",
    "content": "enum ProxyType {\n  direct(\"Direct\"),\n  block(\"Block\"),\n  dns(\"DNS\"),\n  socks(\"SOCKS\"),\n  http(\"HTTP\"),\n  shadowsocks(\"Shadowsocks\"),\n  vmess(\"VMess\"),\n  trojan(\"Trojan\"),\n  naive(\"Naive\"),\n  wireguard(\"WireGuard\"),\n  awg(\"AWG\"),\n  hysteria(\"Hysteria\"),\n  tor(\"Tor\"),\n  ssh(\"SSH\"),\n  shadowtls(\"ShadowTLS\"),\n  shadowsocksr(\"ShadowsocksR\"),\n  vless(\"VLESS\"),\n  tuic(\"TUIC\"),\n  hysteria2(\"Hysteria2\"),\n  mieru(\"Mieru\"),\n\n  selector(\"Selector\"),\n  urltest(\"URLTest\"),\n  balancer(\"Balancer\"),\n  warp(\"Warp\"),\n\n  xvless(\"xVLESS\"),\n  xvmess(\"xVMess\"),\n  xtrojan(\"xTrojan\"),\n  xfreedom(\"xFragment\"),\n  xshadowsocks(\"xShadowsocks\"),\n  xsocks(\"xSocks\"),\n  invalid(\"Invalid\"),\n  unknown(\"Unknown\");\n\n  const ProxyType(this.label);\n\n  final String label;\n\n  String get key => name;\n\n  static List<ProxyType> groupValues = [selector, urltest, balancer];\n\n  bool get isGroup => ProxyType.groupValues.contains(this);\n  static final Map<String, ProxyType> _keyMap = Map.fromEntries(ProxyType.values.map((e) => MapEntry(e.key, e)));\n  static ProxyType fromJson(dynamic type) => _keyMap[(type as String?)?.toLowerCase()] ?? ProxyType.unknown;\n}\n"
  },
  {
    "path": "lib/singbox/model/singbox_rule.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\n\npart 'singbox_rule.freezed.dart';\npart 'singbox_rule.g.dart';\n\n@freezed\nclass SingboxRule with _$SingboxRule {\n  const SingboxRule._();\n\n  @JsonSerializable(fieldRename: FieldRename.kebab)\n  const factory SingboxRule({\n    String? ruleSetUrl,\n    String? domains,\n    String? ip,\n    String? port,\n    String? protocol,\n    @Default(RuleNetwork.tcpAndUdp) RuleNetwork network,\n    @Default(RuleOutbound.proxy) RuleOutbound outbound,\n  }) = _SingboxRule;\n\n  factory SingboxRule.fromJson(Map<String, dynamic> json) => _$SingboxRuleFromJson(json);\n}\n\nenum RuleOutbound { proxy, bypass, block }\n\n@JsonEnum(valueField: 'key')\nenum RuleNetwork {\n  tcpAndUdp(\"\"),\n  tcp(\"tcp\"),\n  udp(\"udp\");\n\n  const RuleNetwork(this.key);\n\n  final String? key;\n}\n"
  },
  {
    "path": "lib/singbox/model/singbox_stats.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\n\npart 'singbox_stats.freezed.dart';\npart 'singbox_stats.g.dart';\n\n@freezed\nclass SingboxStats with _$SingboxStats {\n  const SingboxStats._();\n\n  @JsonSerializable(fieldRename: FieldRename.kebab)\n  const factory SingboxStats({\n    required int connectionsIn,\n    required int connectionsOut,\n    required int uplink,\n    required int downlink,\n    required int uplinkTotal,\n    required int downlinkTotal,\n  }) = _SingboxStats;\n\n  factory SingboxStats.fromJson(Map<String, dynamic> json) => _$SingboxStatsFromJson(json);\n}\n"
  },
  {
    "path": "lib/singbox/model/warp_account.dart",
    "content": "import 'dart:convert';\n\ntypedef WarpResponse = ({String log, String accountId, String accessToken, String wireguardConfig});\n\nWarpResponse warpFromJson(dynamic json) {\n  if (json case {\n    \"account-id\": final String newAccountId,\n    \"access-token\": final String newAccessToken,\n    \"log\": final String log,\n    \"config\": final Map<String, dynamic> wireguardConfig,\n  }) {\n    return (\n      log: log,\n      accountId: newAccountId,\n      accessToken: newAccessToken,\n      wireguardConfig: jsonEncode(wireguardConfig),\n    );\n  }\n  throw Exception(\"invalid response\");\n}\n"
  },
  {
    "path": "lib/utils/alerts.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:toastification/toastification.dart';\n\nenum AlertType {\n  info,\n  error,\n  success;\n\n  ToastificationType get _toastificationType => switch (this) {\n    success => ToastificationType.success,\n    error => ToastificationType.error,\n    info => ToastificationType.info,\n  };\n}\n\nclass CustomToast extends StatelessWidget {\n  const CustomToast(this.message, {this.type = AlertType.info, this.icon, this.duration = const Duration(seconds: 3)});\n\n  const CustomToast.error(this.message, {this.duration = const Duration(seconds: 5)})\n    : type = AlertType.error,\n      icon = FluentIcons.error_circle_24_regular;\n\n  const CustomToast.success(this.message, {this.duration = const Duration(seconds: 3)})\n    : type = AlertType.success,\n      icon = FluentIcons.checkmark_24_regular;\n\n  final String message;\n  final AlertType type;\n  final IconData? icon;\n  final Duration duration;\n\n  @override\n  Widget build(BuildContext context) {\n    final scheme = Theme.of(context).colorScheme;\n    final color = switch (type) {\n      AlertType.info => null,\n      AlertType.error => scheme.error,\n      AlertType.success => scheme.tertiary,\n    };\n\n    return Container(\n      decoration: BoxDecoration(\n        borderRadius: const BorderRadius.all(Radius.circular(4)),\n        color: Theme.of(context).colorScheme.surface,\n      ),\n      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),\n      child: Row(\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          if (icon != null) ...[Icon(icon, color: color), const SizedBox(width: 8)],\n          Flexible(child: Text(message)),\n        ],\n      ),\n    );\n  }\n\n  void show(BuildContext context) {\n    toastification.show(\n      context: context,\n      title: Text(message),\n      type: type._toastificationType,\n      alignment: Alignment.bottomLeft,\n      autoCloseDuration: duration,\n      style: ToastificationStyle.fillColored,\n      pauseOnHover: true,\n      showProgressBar: false,\n      dragToClose: true,\n      closeOnClick: true,\n      closeButtonShowType: CloseButtonShowType.onHover,\n    );\n  }\n}\n"
  },
  {
    "path": "lib/utils/async_mutation.dart",
    "content": "// ignore_for_file: unreachable_switch_case\n\nimport 'package:flutter/material.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:freezed_annotation/freezed_annotation.dart';\n\npart 'async_mutation.freezed.dart';\n\n// TODO: test and improve\n\n@freezed\nclass AsyncMutation with _$AsyncMutation {\n  const AsyncMutation._();\n\n  const factory AsyncMutation.idle() = Idle;\n  const factory AsyncMutation.inProgress() = InProgress;\n  const factory AsyncMutation.fail(Object error, StackTrace stackTrace) = Fail;\n  const factory AsyncMutation.success() = Success;\n\n  bool get isInProgress => this is InProgress;\n}\n\n/// temporary(and hacky) way to manage async mutations\n({AsyncMutation state, ValueChanged<Future<T>> setFuture, ValueChanged<void Function(Object error)> setOnFailure})\nuseMutation<T>({void Function(Object error)? initialOnFailure, void Function()? initialOnSuccess}) {\n  final mutationUpdate = useState<Future<T>?>(null);\n  final mutationState = useFuture(mutationUpdate.value);\n  final failureCallBack = useValueNotifier<void Function(Object error)?>(initialOnFailure);\n  final successCallBack = useValueNotifier<void Function()?>(initialOnSuccess);\n\n  final mapped = useMemoized(() {\n    return switch (mutationState.connectionState) {\n      ConnectionState.none => const Idle(),\n      ConnectionState.waiting => const InProgress(),\n      _ => mutationState.hasError ? Fail(mutationState.error!, mutationState.stackTrace!) : const Success(),\n    };\n  }, [mutationState]);\n\n  // one-of callback in failure\n  useMemoized(() {\n    if (mapped case Fail(:final error)) {\n      // if callback tries to build widget(show snackbar for example) this will prevent exceptions\n      WidgetsBinding.instance.addPostFrameCallback((_) => failureCallBack.value?.call(error));\n    }\n    if (mapped case Success()) {\n      WidgetsBinding.instance.addPostFrameCallback((_) => successCallBack.value?.call());\n    }\n  }, [mapped, failureCallBack.value, successCallBack.value]);\n\n  return (\n    state: mapped,\n    setFuture: (future) => mutationUpdate.value = future,\n    setOnFailure: (onFailure) => failureCallBack.value = onFailure,\n  );\n}\n"
  },
  {
    "path": "lib/utils/bottom_sheet_page.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass BottomSheetPage extends Page {\n  const BottomSheetPage({super.key, super.name, required this.builder, this.fixed = false});\n\n  final Widget Function(ScrollController? controller) builder;\n  final bool fixed;\n\n  @override\n  Route<void> createRoute(BuildContext context) {\n    return ModalBottomSheetRoute(\n      settings: this,\n      isScrollControlled: true,\n      useSafeArea: true,\n      showDragHandle: true,\n      builder: (_) {\n        if (!fixed) {\n          return DraggableScrollableSheet(expand: false, builder: (_, scrollController) => builder(scrollController));\n        }\n        return builder(null);\n      },\n    );\n  }\n}\n"
  },
  {
    "path": "lib/utils/callback_debouncer.dart",
    "content": "import 'dart:async';\n\nimport 'package:flutter/foundation.dart';\n\nclass CallbackDebouncer {\n  CallbackDebouncer(this._delay);\n\n  final Duration _delay;\n  Timer? _timer;\n\n  /// Calls the given [callback] after the given duration has passed.\n  void call(VoidCallback callback) {\n    if (_delay == Duration.zero) {\n      callback();\n    } else {\n      _timer?.cancel();\n      _timer = Timer(_delay, callback);\n    }\n  }\n\n  /// Stops any running timers and disposes this instance.\n  void dispose() {\n    _timer?.cancel();\n  }\n}\n"
  },
  {
    "path": "lib/utils/custom_loggers.dart",
    "content": "import 'package:loggy/loggy.dart';\n\n/// application layer logger\n///\n/// used in notifiers and controllers\nmixin AppLogger implements LoggyType {\n  @override\n  Loggy<AppLogger> get loggy => Loggy<AppLogger>('$runtimeType');\n}\n\n/// presentation layer logger\n///\n/// used in widgets and ui\nmixin PresLogger implements LoggyType {\n  @override\n  Loggy<PresLogger> get loggy => Loggy<PresLogger>('$runtimeType');\n}\n\n/// data layer logger\n///\n/// used in Repositories, DAOs, Services\nmixin InfraLogger implements LoggyType {\n  @override\n  Loggy<InfraLogger> get loggy => Loggy<InfraLogger>('$runtimeType');\n}\n\nabstract class LoggerMixin {\n  LoggerMixin(this.loggy);\n\n  final Loggy loggy;\n}\n"
  },
  {
    "path": "lib/utils/custom_text_form_field.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:hiddify/utils/text_utils.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass CustomTextFormField extends HookConsumerWidget {\n  const CustomTextFormField({\n    super.key,\n    this.onChanged,\n    this.validator,\n    this.controller,\n    this.inputFormatters,\n    this.initialValue = '',\n    this.suffixIcon,\n    this.label,\n    this.hint,\n    this.maxLines,\n    this.isDense = false,\n    this.autoValidate = false,\n    this.autoCorrect = false,\n  });\n\n  final ValueChanged<String>? onChanged;\n  final String? Function(String? value)? validator;\n  final TextEditingController? controller;\n  final List<TextInputFormatter>? inputFormatters;\n  final String initialValue;\n  final Widget? suffixIcon;\n  final String? label;\n  final String? hint;\n  final int? maxLines;\n  final bool isDense;\n  final bool autoValidate;\n  final bool autoCorrect;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final textController = controller ?? useTextEditingController(text: initialValue);\n    final effectiveConstraints = isDense ? const BoxConstraints(maxHeight: 56) : null;\n    final effectiveBorder = isDense\n        ? OutlineInputBorder(borderRadius: BorderRadius.circular(36), borderSide: BorderSide.none)\n        : null;\n\n    return TextFormField(\n      controller: textController,\n      textCapitalization: TextCapitalization.sentences,\n      maxLines: maxLines,\n      onChanged: onChanged,\n      textDirection: textController.textDirection,\n      decoration: InputDecoration(\n        isDense: true,\n        label: label != null ? Text(label!) : null,\n        hintText: hint,\n        hintStyle: Theme.of(context).textTheme.bodySmall,\n        constraints: effectiveConstraints,\n        suffixIcon: suffixIcon,\n        border: effectiveBorder,\n        enabledBorder: effectiveBorder,\n        errorBorder: effectiveBorder,\n        focusedBorder: effectiveBorder,\n        focusedErrorBorder: effectiveBorder,\n      ),\n      validator: validator,\n      textInputAction: TextInputAction.next,\n      inputFormatters: inputFormatters,\n      autovalidateMode: autoValidate ? AutovalidateMode.always : AutovalidateMode.disabled,\n      autocorrect: autoCorrect,\n    );\n  }\n}\n"
  },
  {
    "path": "lib/utils/date_time_formatter.dart",
    "content": "import 'package:intl/intl.dart';\n\nextension DateTimeFormatter on DateTime {\n  String format() {\n    return DateFormat.yMMMd().add_Hm().format(this);\n  }\n}\n"
  },
  {
    "path": "lib/utils/link_parsers.dart",
    "content": "import 'dart:convert';\n\nimport 'package:hiddify/utils/validators.dart';\n\ntypedef ProfileLink = ({String url, String name});\n\n// TODO: test and improve\nabstract class LinkParser {\n  static String generateSubShareLink(String url, [String? name]) {\n    final uri = Uri.tryParse(url);\n    if (uri == null) return '';\n    final modifiedUri = Uri(\n      scheme: uri.scheme,\n      host: uri.host,\n      path: uri.path,\n      query: uri.query,\n      fragment: name ?? uri.fragment,\n    );\n    // return 'hiddify://import/$modifiedUri';\n    return '$modifiedUri';\n  }\n\n  // protocols schemas\n  static const protocols = ['hiddify', 'v2ray', 'v2rayn', 'v2rayng', 'clash', 'clashmeta', 'sing-box'];\n\n  static ProfileLink? parse(String link) {\n    return simple(link) ?? deep(link);\n  }\n\n  static ProfileLink? simple(String link) {\n    if (!isUrl(link)) return null;\n    final uri = Uri.parse(link.trim());\n    return (url: uri.toString(), name: uri.queryParameters['name'] ?? '');\n  }\n\n  static ProfileLink? deep(String link) {\n    final uri = Uri.tryParse(link.trim());\n    if (uri == null || !uri.hasScheme || !uri.hasAuthority) return null;\n    final queryParams = uri.queryParameters;\n    switch (uri.scheme) {\n      case 'hiddify':\n        if (queryParams.containsKey('url')) {\n          return (url: queryParams['url']!, name: queryParams['name'] ?? '');\n        } else {\n          return (url: uri.path.substring(1) + (uri.hasQuery ? \"?${uri.query}\" : \"\"), name: uri.fragment);\n        }\n      case 'v2ray' || 'v2rayn' || 'v2rayng' || 'clash' || 'clashmeta' || 'sing-box':\n        return queryParams.containsKey('url') ? (url: queryParams['url']!, name: queryParams['name'] ?? '') : null;\n      default:\n        return null;\n    }\n  }\n}\n\nString safeDecodeBase64(String str) {\n  try {\n    return utf8.decode(base64Decode(str));\n  } catch (e) {\n    return str;\n  }\n}\n"
  },
  {
    "path": "lib/utils/mutation_state.dart",
    "content": "import 'package:freezed_annotation/freezed_annotation.dart';\nimport 'package:hiddify/core/model/failures.dart';\n\npart 'mutation_state.freezed.dart';\n\n// TODO: remove\n@freezed\nclass MutationState<F extends Failure> with _$MutationState<F> {\n  const MutationState._();\n\n  const factory MutationState.initial() = MutationInitial<F>;\n  const factory MutationState.inProgress() = MutationInProgress<F>;\n  const factory MutationState.failure(Failure failure) = MutationFailure<F>;\n  const factory MutationState.success() = MutationSuccess<F>;\n\n  bool get isInProgress => this is MutationInProgress;\n}\n"
  },
  {
    "path": "lib/utils/number_formatters.dart",
    "content": "import 'package:humanizer/humanizer.dart';\n\nextension ByteFormatter on int {\n  String size() => bytes().toString();\n\n  static final _sizeOfFormat = InformationSizeFormat(permissibleValueUnits: {InformationUnit.gibibyte});\n\n  String sizeGB() => _sizeOfFormat.format(bytes());\n\n  String sizeOf(int total) => \"${_sizeOfFormat.format(bytes())} / ${_sizeOfFormat.format(total.bytes())}\";\n\n  bool isInfinitSize() => bytes().terabytes.toDouble() > 10;\n\n  static final _rateFormat = InformationRateFormat(permissibleRateUnits: {RateUnit.second});\n\n  String speed() => _rateFormat.format(bytes().per(const Duration(seconds: 1)));\n}\n"
  },
  {
    "path": "lib/utils/placeholders.dart",
    "content": "import 'package:fluentui_system_icons/fluentui_system_icons.dart';\nimport 'package:flutter/material.dart';\nimport 'package:gap/gap.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\n// TODO: improve\nclass SliverBodyPlaceholder extends HookConsumerWidget {\n  const SliverBodyPlaceholder(this.children, {super.key});\n\n  final List<Widget> children;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    return SliverFillRemaining(\n      hasScrollBody: false,\n      child: Column(mainAxisAlignment: MainAxisAlignment.center, children: children),\n    );\n  }\n}\n\nclass SliverLoadingBodyPlaceholder extends HookConsumerWidget {\n  const SliverLoadingBodyPlaceholder({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    return const SliverFillRemaining(\n      hasScrollBody: false,\n      child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [CircularProgressIndicator()]),\n    );\n  }\n}\n\nclass SliverErrorBodyPlaceholder extends HookConsumerWidget {\n  const SliverErrorBodyPlaceholder(this.msg, {super.key, this.icon = FluentIcons.error_circle_24_regular});\n\n  final String msg;\n  final IconData? icon;\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    return SliverFillRemaining(\n      hasScrollBody: false,\n      child: Column(\n        mainAxisAlignment: MainAxisAlignment.center,\n        children: [\n          if (icon != null) ...[Icon(icon), const Gap(16)],\n          Text(msg),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/utils/platform_utils.dart",
    "content": "import 'dart:io';\n\nimport 'package:flutter/foundation.dart';\n\nabstract class PlatformUtils {\n  static bool get isWindows => !kIsWeb && (Platform.isWindows);\n\n  static bool get isDesktop => !kIsWeb && (Platform.isLinux || Platform.isWindows || Platform.isMacOS);\n\n  static bool get isInAppStore => !kIsWeb && (Platform.isIOS);\n\n  static bool get isMobile => !kIsWeb && (Platform.isAndroid || Platform.isIOS);\n\n  static bool get isWeb => kIsWeb;\n\n  static bool get isLinux => !kIsWeb && Platform.isLinux;\n\n  static bool get isMacOS => !kIsWeb && Platform.isMacOS;\n\n  static bool get isIOS => !kIsWeb && Platform.isIOS;\n\n  static bool get isAndroid => !kIsWeb && Platform.isAndroid;\n}\n"
  },
  {
    "path": "lib/utils/riverpod_utils.dart",
    "content": "import 'dart:async';\n\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nextension RefLifeCycle<T> on AutoDisposeRef<T> {\n  void disposeDelay(Duration duration) {\n    final link = keepAlive();\n    Timer? timer;\n\n    onCancel(() {\n      timer?.cancel();\n      timer = Timer(duration, link.close);\n    });\n\n    onDispose(() {\n      timer?.cancel();\n    });\n\n    onResume(() {\n      timer?.cancel();\n    });\n  }\n}\n"
  },
  {
    "path": "lib/utils/sentry_riverpod_observer.dart",
    "content": "import 'package:hooks_riverpod/hooks_riverpod.dart';\nimport 'package:sentry_flutter/sentry_flutter.dart';\n\nclass SentryRiverpodObserver extends ProviderObserver {\n  void addBreadcrumb(String message, {Map<String, dynamic>? data}) {\n    Sentry.addBreadcrumb(Breadcrumb(category: \"Provider\", message: message, data: data));\n  }\n\n  @override\n  void didAddProvider(ProviderBase<Object?> provider, Object? value, ProviderContainer container) {\n    super.didAddProvider(provider, value, container);\n    addBreadcrumb(\n      'Provider [${provider.name ?? provider.runtimeType}] was ADDED',\n      data: value != null ? {\"initial-value\": value} : null,\n    );\n  }\n\n  @override\n  void didUpdateProvider(\n    ProviderBase<Object?> provider,\n    Object? previousValue,\n    Object? newValue,\n    ProviderContainer container,\n  ) {\n    super.didUpdateProvider(provider, previousValue, newValue, container);\n    addBreadcrumb(\n      'Provider [${provider.name ?? provider.runtimeType}] was UPDATED',\n      data: {\"new-value\": newValue, \"old-value\": previousValue},\n    );\n  }\n}\n"
  },
  {
    "path": "lib/utils/sentry_utils.dart",
    "content": "import 'dart:io';\n\nimport 'package:dio/dio.dart';\nimport 'package:hiddify/core/model/failures.dart';\nimport 'package:hiddify/features/proxy/model/proxy_failure.dart';\nimport 'package:riverpod_annotation/riverpod_annotation.dart';\nimport 'package:sentry_flutter/sentry_flutter.dart';\n\nFutureOr<SentryEvent?> sentryBeforeSend(SentryEvent event, {Hint? hint}) {\n  if (canSendEvent(event.throwable)) return event;\n  return null;\n}\n\nbool canSendEvent(dynamic throwable) {\n  return switch (throwable) {\n    UnexpectedFailure(:final error) => canSendEvent(error),\n    DioException _ => false,\n    SocketException _ => false,\n    UnknownIp _ => false,\n    HttpException _ => false,\n    HandshakeException _ => false,\n    ExpectedFailure _ => false,\n    ExpectedMeasuredFailure _ => false,\n    _ => true,\n  };\n}\n\nbool canLogEvent(dynamic throwable) => switch (throwable) {\n  ExpectedMeasuredFailure _ => true,\n  _ => canSendEvent(throwable),\n};\n"
  },
  {
    "path": "lib/utils/text_utils.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:intl/intl.dart' as intl;\n\nextension TextAlignX on BuildContext {\n  bool get isRtl => Directionality.of(this) == TextDirection.rtl;\n\n  TextAlign get textAlign {\n    if (isRtl) {\n      return TextAlign.right;\n    } else {\n      return TextAlign.left;\n    }\n  }\n}\n\nextension StringX on String {\n  TextDirection get textDirection {\n    return intl.Bidi.detectRtlDirectionality(this) ? TextDirection.rtl : TextDirection.ltr;\n  }\n}\n\nextension TextEditingControllerX on TextEditingController {\n  TextDirection? get textDirection {\n    if (text.isEmpty) return null;\n    return text.textDirection;\n  }\n}\n"
  },
  {
    "path": "lib/utils/uri_utils.dart",
    "content": "import 'dart:io';\n\nimport 'package:hiddify/utils/custom_loggers.dart';\nimport 'package:loggy/loggy.dart';\nimport 'package:share_plus/share_plus.dart';\nimport 'package:url_launcher/url_launcher.dart';\n\nabstract class UriUtils {\n  static final loggy = Loggy<InfraLogger>(\"UriUtils\");\n\n  static Future<bool> tryShareOrLaunchFile(Uri uri, {Uri? fileOrDir}) async {\n    if (Platform.isWindows || Platform.isLinux) {\n      return tryLaunch(fileOrDir ?? uri);\n    }\n    return tryShareFile(uri);\n  }\n\n  static Future<bool> tryLaunch(Uri uri) async {\n    try {\n      loggy.debug(\"launching [$uri]\");\n      if (!await canLaunchUrl(uri)) {\n        loggy.warning(\"can't launch [$uri]\");\n        return false;\n      }\n      return launchUrl(uri, mode: LaunchMode.externalApplication);\n    } catch (e, stackTrace) {\n      loggy.warning(\"error launching [$uri]\", e, stackTrace);\n      return false;\n    }\n  }\n\n  static Future<bool> tryShareFile(Uri uri, {String? mimeType}) async {\n    try {\n      loggy.debug(\"sharing [$uri]\");\n      final file = XFile(uri.path, mimeType: mimeType);\n      final result = await Share.shareXFiles([file]);\n      loggy.debug(\"share result: ${result.raw}\");\n      return result.status == ShareResultStatus.success;\n    } catch (e, stackTrace) {\n      loggy.warning(\"error sharing file [$uri]\", e, stackTrace);\n      return false;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/utils/utils.dart",
    "content": "export 'alerts.dart';\nexport 'async_mutation.dart';\nexport 'bottom_sheet_page.dart';\nexport 'callback_debouncer.dart';\nexport 'custom_loggers.dart';\nexport 'custom_text_form_field.dart';\nexport 'date_time_formatter.dart';\nexport 'link_parsers.dart';\nexport 'mutation_state.dart';\nexport 'number_formatters.dart';\nexport 'placeholders.dart';\nexport 'platform_utils.dart';\nexport 'sentry_riverpod_observer.dart';\nexport 'sentry_utils.dart';\nexport 'text_utils.dart';\nexport 'uri_utils.dart';\nexport 'validators.dart';\n"
  },
  {
    "path": "lib/utils/validators.dart",
    "content": "/// https://gist.github.com/dperini/729294\nfinal _urlRegex = RegExp(\n  // r\"^(?:(?:(?:https?|ftp):)?\\/\\/)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z0-9\\u00a1-\\uffff][a-z0-9\\u00a1-\\uffff_-]{0,62})?[a-z0-9\\u00a1-\\uffff]\\.)+(?:[a-z\\u00a1-\\uffff]{2,}\\.?))(?::\\d{2,5})?(?:[/?#]\\S*)?$\",\n  r'^(?:(?:https?|ftp):\\/\\/)(?:\\S+(?::\\S*)?@)?(?:(?:[0-9]{1,3}\\.){3}[0-9]{1,3}|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?#?.*$',\n);\n\n/// https://stackoverflow.com/a/12968117\nfinal _portRegex = RegExp(r\"^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$\");\n\n// android package-name\n// RegExp(r'^([A-Za-z]{1}[A-Za-z\\d_]*\\.)+[A-Za-z][A-Za-z\\d_]*$');\n// windows prcess name\n// RegExp(r\"^(?!\\s)[a-zA-Z\\d\\s\\-\\]\\^!@#$%&()[+_=~'`.,;]+(?<![\\s.]|CON|PRN|AUX|NUL|COM[\\d]|COM[¹²³]|LPT[\\d]|LPT[¹²³])\\.(exe|bat|cmd|com)$\", caseSensitive: false);\n// linux process name\n// RegExp(r'''^(?!\\s)[a-zA-Z\\d\\s\\-\\]\\^\\\\!?@#$%&*()[<>+_=|~'`\".,:;]+(?<!\\s)$''');\n// mac process name\n// RegExp(r'''^(?!\\s)[a-zA-Z\\d\\s\\-\\]\\^\\\\!?@#$%&*()[<>+_=|~'`\".,;]+(?<!\\s)$''');\n// domain\n// RegExp(r'^((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+([a-z]{2,63}|xn--[a-z0-9-]{1,63})$');\n\nfinal _processNameWindowsRegex = RegExp(r'^[^<>:\"\\\\/|?*]+(?<![\\s.])\\.(exe|bat|cmd|com)$', caseSensitive: false);\n\nfinal _processNameLinuxRegex = RegExp(r'^[^\\\\]+$');\n\nfinal _processNameMacOSRegex = RegExp(r'^[^\\\\:]+$');\n\nfinal _processPathWindowsRegex = RegExp(\n  r'^[a-zA-Z]:\\\\([^<>:\"\\\\/|?*]*(?<!\\\\)\\\\)*[^<>:\"\\\\/|?*]+(?<![\\s.])\\.(exe|bat|cmd|com)$',\n  caseSensitive: false,\n);\n\nfinal _processPathLinuxRegex = RegExp(r'^/([^/]*(?<!/)/)*[^/]+$');\n\nfinal _processPathMacOSRegex = RegExp(r'^/([^/:]*(?<!/)/)*[^/:]+$');\n\nfinal _portOrPortRangeRegex = RegExp(\n  r'^(65000|6[0-4]\\d{3}|[1-5]\\d{4}|[1-9]\\d{0,3})(-(65000|6[0-4]\\d{3}|[1-5]\\d{4}|[1-9]\\d{0,3}))?$',\n);\n\nfinal _ipCidrRegex = RegExp(\n  r'^(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2}).(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})(/(3[0-2]|[1-2]\\d|\\d))?$',\n);\n\nfinal _domainRegex = RegExp(r'^([a-zA-Z\\d\\-]+\\.)+[a-zA-Z\\d\\-]{2,}$', caseSensitive: false);\n\nfinal _domainSuffix = RegExp(r'^\\.[a-zA-Z\\d\\-]{2,}$', caseSensitive: false);\n\n/// https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url/3809435#3809435\nbool isUrl(String input) {\n  return _urlRegex.hasMatch(input.trim().toLowerCase());\n}\n\nbool isPort(String input) {\n  return _portRegex.hasMatch(input);\n}\n\nbool isProcessName(String input) {\n  if (_processNameWindowsRegex.hasMatch(input) ||\n      _processNameLinuxRegex.hasMatch(input) ||\n      _processNameMacOSRegex.hasMatch(input)) {\n    return true;\n  } else {\n    return false;\n  }\n}\n\nbool isProcessPath(String input) {\n  if (_processPathWindowsRegex.hasMatch(input) ||\n      _processPathLinuxRegex.hasMatch(input) ||\n      _processPathMacOSRegex.hasMatch(input)) {\n    return true;\n  } else {\n    return false;\n  }\n}\n\nbool isPortOrPortRange(String input) {\n  return _portOrPortRangeRegex.hasMatch(input);\n}\n\nbool isIpCidr(String input) {\n  return _ipCidrRegex.hasMatch(input);\n}\n\nbool isDomain(String input) {\n  return _domainRegex.hasMatch(input);\n}\n\nbool isDomainSuffix(String input) {\n  return _domainSuffix.hasMatch(input);\n}\n"
  },
  {
    "path": "linux/.gitignore",
    "content": "flutter/ephemeral\n"
  },
  {
    "path": "linux/.stignore",
    "content": "/flutter/ephemeral\n"
  },
  {
    "path": "linux/CMakeLists.txt",
    "content": "# Project-level configuration.\ncmake_minimum_required(VERSION 3.10)\nproject(runner LANGUAGES CXX)\n\n# The name of the executable created for the application. Change this to change\n# the on-disk name of your application.\nset(BINARY_NAME \"hiddify\")\n# The unique GTK application identifier for this application. See:\n# https://wiki.gnome.org/HowDoI/ChooseApplicationID\nset(APPLICATION_ID \"app.hiddify.com\")\n\n# Explicitly opt in to modern CMake behaviors to avoid warnings with recent\n# versions of CMake.\ncmake_policy(SET CMP0063 NEW)\n\n# Load bundled libraries from the lib/ directory relative to the binary.\nset(CMAKE_INSTALL_RPATH \"$ORIGIN/lib\")\n\n# Root filesystem for cross-building.\nif(FLUTTER_TARGET_PLATFORM_SYSROOT)\n  set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})\n  set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})\n  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\n  set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)\n  set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)\n  set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)\nendif()\n\n# Define build configuration options.\nif(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)\n  set(CMAKE_BUILD_TYPE \"Debug\" CACHE\n    STRING \"Flutter build mode\" FORCE)\n  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS\n    \"Debug\" \"Profile\" \"Release\")\nendif()\n\n# Compilation settings that should be applied to most targets.\n#\n# Be cautious about adding new options here, as plugins use this function by\n# default. In most cases, you should add new options to specific targets instead\n# of modifying this function.\nfunction(APPLY_STANDARD_SETTINGS TARGET)\n  target_compile_features(${TARGET} PUBLIC cxx_std_17)\n  target_compile_options(${TARGET} PRIVATE -Wall -Werror)\n  target_compile_options(${TARGET} PRIVATE \"$<$<NOT:$<CONFIG:Debug>>:-O3>\")\n  target_compile_definitions(${TARGET} PRIVATE \"$<$<NOT:$<CONFIG:Debug>>:NDEBUG>\")\nendfunction()\n\n# Flutter library and tool build rules.\nset(FLUTTER_MANAGED_DIR \"${CMAKE_CURRENT_SOURCE_DIR}/flutter\")\nadd_subdirectory(${FLUTTER_MANAGED_DIR})\n\n# System-level dependencies.\nfind_package(PkgConfig REQUIRED)\npkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)\n\nadd_definitions(-DAPPLICATION_ID=\"${APPLICATION_ID}\")\n\n# Define the application target. To change its name, change BINARY_NAME above,\n# not the value here, or `flutter run` will no longer work.\n#\n# Any new source files that you add to the application should be added here.\nadd_executable(${BINARY_NAME}\n  \"main.cc\"\n  \"my_application.cc\"\n  \"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc\"\n)\n\n# Apply the standard set of build settings. This can be removed for applications\n# that need different build settings.\napply_standard_settings(${BINARY_NAME})\n\n# Add dependency libraries. Add any application-specific dependencies here.\ntarget_link_libraries(${BINARY_NAME} PRIVATE flutter)\ntarget_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)\n\n# Run the Flutter tool portions of the build. This must not be removed.\nadd_dependencies(${BINARY_NAME} flutter_assemble)\n\n# Only the install-generated bundle's copy of the executable will launch\n# correctly, since the resources must in the right relative locations. To avoid\n# people trying to run the unbundled copy, put it in a subdirectory instead of\n# the default top-level location.\nset_target_properties(${BINARY_NAME}\n  PROPERTIES\n  RUNTIME_OUTPUT_DIRECTORY \"${CMAKE_BINARY_DIR}/intermediates_do_not_run\"\n)\n\n\n# Generated plugin build rules, which manage building the plugins and adding\n# them to the application.\ninclude(flutter/generated_plugins.cmake)\n\n\n# === Installation ===\n# By default, \"installing\" just makes a relocatable bundle in the build\n# directory.\nset(BUILD_BUNDLE_DIR \"${PROJECT_BINARY_DIR}/bundle\")\nif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)\n  set(CMAKE_INSTALL_PREFIX \"${BUILD_BUNDLE_DIR}\" CACHE PATH \"...\" FORCE)\nendif()\n\n# Start with a clean build bundle directory every time.\ninstall(CODE \"\n  file(REMOVE_RECURSE \\\"${BUILD_BUNDLE_DIR}/\\\")\n  \" COMPONENT Runtime)\n\nset(INSTALL_BUNDLE_DATA_DIR \"${CMAKE_INSTALL_PREFIX}/data\")\nset(INSTALL_BUNDLE_LIB_DIR \"${CMAKE_INSTALL_PREFIX}/lib\")\n\ninstall(FILES \"../hiddify-core/bin/lib/hiddify-core.so\" DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\n  COMPONENT Runtime)\n\ninstall(\n  FILES \"../hiddify-core/bin/HiddifyCli\" \n  DESTINATION \"${CMAKE_INSTALL_PREFIX}\"\n  PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ\n  COMPONENT Runtime\n)\n\ninstall(TARGETS ${BINARY_NAME} RUNTIME DESTINATION \"${CMAKE_INSTALL_PREFIX}\"\n  COMPONENT Runtime)\n\ninstall(FILES \"${FLUTTER_ICU_DATA_FILE}\" DESTINATION \"${INSTALL_BUNDLE_DATA_DIR}\"\n  COMPONENT Runtime)\n\ninstall(FILES \"${FLUTTER_LIBRARY}\" DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\n  COMPONENT Runtime)\n\nforeach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})\n  install(FILES \"${bundled_library}\"\n    DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\n    COMPONENT Runtime)\nendforeach(bundled_library)\n\n# Copy the native assets provided by the build.dart from all packages.\nset(NATIVE_ASSETS_DIR \"${PROJECT_BUILD_DIR}native_assets/linux/\")\ninstall(DIRECTORY \"${NATIVE_ASSETS_DIR}\"\n   DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\n   COMPONENT Runtime)\n\n# Fully re-copy the assets directory on each build to avoid having stale files\n# from a previous install.\nset(FLUTTER_ASSET_DIR_NAME \"flutter_assets\")\ninstall(CODE \"\n  file(REMOVE_RECURSE \\\"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\\\")\n  \" COMPONENT Runtime)\ninstall(DIRECTORY \"${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}\"\n  DESTINATION \"${INSTALL_BUNDLE_DATA_DIR}\" COMPONENT Runtime)\n\n# Install the AOT library on non-Debug builds only.\nif(NOT CMAKE_BUILD_TYPE MATCHES \"Debug\")\n  install(FILES \"${AOT_LIBRARY}\" DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\n    COMPONENT Runtime)\nendif()\n"
  },
  {
    "path": "linux/flutter/CMakeLists.txt",
    "content": "# This file controls Flutter-level build steps. It should not be edited.\ncmake_minimum_required(VERSION 3.10)\n\nset(EPHEMERAL_DIR \"${CMAKE_CURRENT_SOURCE_DIR}/ephemeral\")\n\n# Configuration provided via flutter tool.\ninclude(${EPHEMERAL_DIR}/generated_config.cmake)\n\n# TODO: Move the rest of this into files in ephemeral. See\n# https://github.com/flutter/flutter/issues/57146.\n\n# Serves the same purpose as list(TRANSFORM ... PREPEND ...),\n# which isn't available in 3.10.\nfunction(list_prepend LIST_NAME PREFIX)\n    set(NEW_LIST \"\")\n    foreach(element ${${LIST_NAME}})\n        list(APPEND NEW_LIST \"${PREFIX}${element}\")\n    endforeach(element)\n    set(${LIST_NAME} \"${NEW_LIST}\" PARENT_SCOPE)\nendfunction()\n\n# === Flutter Library ===\n# System-level dependencies.\nfind_package(PkgConfig REQUIRED)\npkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)\npkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)\npkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)\n\nset(FLUTTER_LIBRARY \"${EPHEMERAL_DIR}/libflutter_linux_gtk.so\")\n\n# Published to parent scope for install step.\nset(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)\nset(FLUTTER_ICU_DATA_FILE \"${EPHEMERAL_DIR}/icudtl.dat\" PARENT_SCOPE)\nset(PROJECT_BUILD_DIR \"${PROJECT_DIR}/build/\" PARENT_SCOPE)\nset(AOT_LIBRARY \"${PROJECT_DIR}/build/lib/libapp.so\" PARENT_SCOPE)\n\nlist(APPEND FLUTTER_LIBRARY_HEADERS\n  \"fl_basic_message_channel.h\"\n  \"fl_binary_codec.h\"\n  \"fl_binary_messenger.h\"\n  \"fl_dart_project.h\"\n  \"fl_engine.h\"\n  \"fl_json_message_codec.h\"\n  \"fl_json_method_codec.h\"\n  \"fl_message_codec.h\"\n  \"fl_method_call.h\"\n  \"fl_method_channel.h\"\n  \"fl_method_codec.h\"\n  \"fl_method_response.h\"\n  \"fl_plugin_registrar.h\"\n  \"fl_plugin_registry.h\"\n  \"fl_standard_message_codec.h\"\n  \"fl_standard_method_codec.h\"\n  \"fl_string_codec.h\"\n  \"fl_value.h\"\n  \"fl_view.h\"\n  \"flutter_linux.h\"\n)\nlist_prepend(FLUTTER_LIBRARY_HEADERS \"${EPHEMERAL_DIR}/flutter_linux/\")\nadd_library(flutter INTERFACE)\ntarget_include_directories(flutter INTERFACE\n  \"${EPHEMERAL_DIR}\"\n)\ntarget_link_libraries(flutter INTERFACE \"${FLUTTER_LIBRARY}\")\ntarget_link_libraries(flutter INTERFACE\n  PkgConfig::GTK\n  PkgConfig::GLIB\n  PkgConfig::GIO\n)\nadd_dependencies(flutter flutter_assemble)\n\n# === Flutter tool backend ===\n# _phony_ is a non-existent file to force this command to run every time,\n# since currently there's no way to get a full input/output list from the\n# flutter tool.\nadd_custom_command(\n  OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}\n    ${CMAKE_CURRENT_BINARY_DIR}/_phony_\n  COMMAND ${CMAKE_COMMAND} -E env\n    ${FLUTTER_TOOL_ENVIRONMENT}\n    \"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh\"\n      ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}\n  VERBATIM\n)\nadd_custom_target(flutter_assemble DEPENDS\n  \"${FLUTTER_LIBRARY}\"\n  ${FLUTTER_LIBRARY_HEADERS}\n)\n"
  },
  {
    "path": "linux/flutter/generated_plugin_registrant.cc",
    "content": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#include \"generated_plugin_registrant.h\"\n\n#include <dynamic_color/dynamic_color_plugin.h>\n#include <gtk/gtk_plugin.h>\n#include <screen_retriever_linux/screen_retriever_linux_plugin.h>\n#include <sentry_flutter/sentry_flutter_plugin.h>\n#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>\n#include <tray_manager/tray_manager_plugin.h>\n#include <url_launcher_linux/url_launcher_plugin.h>\n#include <window_manager/window_manager_plugin.h>\n\nvoid fl_register_plugins(FlPluginRegistry* registry) {\n  g_autoptr(FlPluginRegistrar) dynamic_color_registrar =\n      fl_plugin_registry_get_registrar_for_plugin(registry, \"DynamicColorPlugin\");\n  dynamic_color_plugin_register_with_registrar(dynamic_color_registrar);\n  g_autoptr(FlPluginRegistrar) gtk_registrar =\n      fl_plugin_registry_get_registrar_for_plugin(registry, \"GtkPlugin\");\n  gtk_plugin_register_with_registrar(gtk_registrar);\n  g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar =\n      fl_plugin_registry_get_registrar_for_plugin(registry, \"ScreenRetrieverLinuxPlugin\");\n  screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar);\n  g_autoptr(FlPluginRegistrar) sentry_flutter_registrar =\n      fl_plugin_registry_get_registrar_for_plugin(registry, \"SentryFlutterPlugin\");\n  sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar);\n  g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar =\n      fl_plugin_registry_get_registrar_for_plugin(registry, \"Sqlite3FlutterLibsPlugin\");\n  sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar);\n  g_autoptr(FlPluginRegistrar) tray_manager_registrar =\n      fl_plugin_registry_get_registrar_for_plugin(registry, \"TrayManagerPlugin\");\n  tray_manager_plugin_register_with_registrar(tray_manager_registrar);\n  g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =\n      fl_plugin_registry_get_registrar_for_plugin(registry, \"UrlLauncherPlugin\");\n  url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);\n  g_autoptr(FlPluginRegistrar) window_manager_registrar =\n      fl_plugin_registry_get_registrar_for_plugin(registry, \"WindowManagerPlugin\");\n  window_manager_plugin_register_with_registrar(window_manager_registrar);\n}\n"
  },
  {
    "path": "linux/flutter/generated_plugin_registrant.h",
    "content": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#ifndef GENERATED_PLUGIN_REGISTRANT_\n#define GENERATED_PLUGIN_REGISTRANT_\n\n#include <flutter_linux/flutter_linux.h>\n\n// Registers Flutter plugins.\nvoid fl_register_plugins(FlPluginRegistry* registry);\n\n#endif  // GENERATED_PLUGIN_REGISTRANT_\n"
  },
  {
    "path": "linux/flutter/generated_plugins.cmake",
    "content": "#\n# Generated file, do not edit.\n#\n\nlist(APPEND FLUTTER_PLUGIN_LIST\n  dynamic_color\n  gtk\n  screen_retriever_linux\n  sentry_flutter\n  sqlite3_flutter_libs\n  tray_manager\n  url_launcher_linux\n  window_manager\n)\n\nlist(APPEND FLUTTER_FFI_PLUGIN_LIST\n)\n\nset(PLUGIN_BUNDLED_LIBRARIES)\n\nforeach(plugin ${FLUTTER_PLUGIN_LIST})\n  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})\n  target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)\n  list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)\n  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})\nendforeach(plugin)\n\nforeach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})\n  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})\n  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})\nendforeach(ffi_plugin)\n"
  },
  {
    "path": "linux/main.cc",
    "content": "#include \"my_application.h\"\n\nint main(int argc, char** argv) {\n  g_autoptr(MyApplication) app = my_application_new();\n  return g_application_run(G_APPLICATION(app), argc, argv);\n}\n"
  },
  {
    "path": "linux/my_application.cc",
    "content": "#include \"my_application.h\"\n\n#include <flutter_linux/flutter_linux.h>\n#ifdef GDK_WINDOWING_X11\n#include <gdk/gdkx.h>\n#endif\n\n#include \"flutter/generated_plugin_registrant.h\"\n\nstruct _MyApplication\n{\n  GtkApplication parent_instance;\n  char **dart_entrypoint_arguments;\n};\n\nG_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)\n#define ICON_PATH \"./hiddify.png\"\n\n// Implements GApplication::activate.\nstatic void my_application_activate(GApplication *application)\n{\n  MyApplication *self = MY_APPLICATION(application);\n\n  GList *windows = gtk_application_get_windows(GTK_APPLICATION(application));\n  if (windows)\n  {\n    gtk_window_present(GTK_WINDOW(windows->data));\n    return;\n  }\n\n  GtkWindow *window =\n      GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));\n  gtk_window_set_icon_from_file(window, ICON_PATH, NULL);\n\n  // Use a header bar when running in GNOME as this is the common style used\n  // by applications and is the setup most users will be using (e.g. Ubuntu\n  // desktop).\n  // If running on X and not using GNOME then just use a traditional title bar\n  // in case the window manager does more exotic layout, e.g. tiling.\n  // If running on Wayland assume the header bar will work (may need changing\n  // if future cases occur).\n  gboolean use_header_bar = TRUE;\n#ifdef GDK_WINDOWING_X11\n  GdkScreen *screen = gtk_window_get_screen(window);\n  if (GDK_IS_X11_SCREEN(screen))\n  {\n    const gchar *wm_name = gdk_x11_screen_get_window_manager_name(screen);\n    if (g_strcmp0(wm_name, \"GNOME Shell\") != 0)\n    {\n      use_header_bar = FALSE;\n    }\n  }\n#endif\n  if (use_header_bar)\n  {\n    GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());\n    gtk_widget_show(GTK_WIDGET(header_bar));\n    gtk_header_bar_set_title(header_bar, \"Hiddify\");\n    gtk_header_bar_set_show_close_button(header_bar, TRUE);\n    gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));\n  }\n  else\n  {\n    gtk_window_set_title(window, \"Hiddify\");\n  }\n\n  gtk_window_set_default_size(window, 1280, 720);\n  gtk_widget_show(GTK_WIDGET(window));\n\n  g_autoptr(FlDartProject) project = fl_dart_project_new();\n  fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);\n\n  FlView *view = fl_view_new(project);\n  gtk_widget_show(GTK_WIDGET(view));\n  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));\n\n  fl_register_plugins(FL_PLUGIN_REGISTRY(view));\n  // Flutter 3.24 breaks the gtk_widget_realize solution: https://github.com/leanflutter/window_manager/issues/179#issuecomment-2299534856\n  gtk_widget_hide(GTK_WIDGET(window));\n\n  gtk_widget_grab_focus(GTK_WIDGET(view));\n}\n\n// Implements GApplication::local_command_line.\nstatic gboolean my_application_local_command_line(GApplication *application, gchar ***arguments, int *exit_status)\n{\n  MyApplication *self = MY_APPLICATION(application);\n  // Strip out the first argument as it is the binary name.\n  self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);\n\n  g_autoptr(GError) error = nullptr;\n  if (!g_application_register(application, nullptr, &error))\n  {\n    g_warning(\"Failed to register: %s\", error->message);\n    *exit_status = 1;\n    return TRUE;\n  }\n\n  g_application_activate(application);\n  *exit_status = 0;\n\n  return FALSE;\n}\n\n// Implements GApplication::startup.\nstatic void my_application_startup(GApplication *application)\n{\n  // MyApplication* self = MY_APPLICATION(object);\n\n  // Perform any actions required at application startup.\n\n  G_APPLICATION_CLASS(my_application_parent_class)->startup(application);\n}\n\n// Implements GApplication::shutdown.\nstatic void my_application_shutdown(GApplication *application)\n{\n  // MyApplication* self = MY_APPLICATION(object);\n\n  // Perform any actions required at application shutdown.\n\n  G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);\n}\n\n// Implements GObject::dispose.\nstatic void my_application_dispose(GObject *object)\n{\n  MyApplication *self = MY_APPLICATION(object);\n  g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);\n  G_OBJECT_CLASS(my_application_parent_class)->dispose(object);\n}\n\nstatic void my_application_class_init(MyApplicationClass *klass)\n{\n  G_APPLICATION_CLASS(klass)->activate = my_application_activate;\n  G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;\n  G_APPLICATION_CLASS(klass)->startup = my_application_startup;\n  G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;\n  G_OBJECT_CLASS(klass)->dispose = my_application_dispose;\n}\n\nstatic void my_application_init(MyApplication *self) {}\n\nMyApplication *my_application_new()\n{\n  g_set_prgname(APPLICATION_ID);\n\n  return MY_APPLICATION(g_object_new(my_application_get_type(),\n                                     \"application-id\", APPLICATION_ID,\n                                     \"flags\", G_APPLICATION_HANDLES_COMMAND_LINE | G_APPLICATION_HANDLES_OPEN,\n                                     nullptr));\n}\n"
  },
  {
    "path": "linux/my_application.h",
    "content": "#ifndef FLUTTER_MY_APPLICATION_H_\n#define FLUTTER_MY_APPLICATION_H_\n\n#include <gtk/gtk.h>\n\nG_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,\n                     GtkApplication)\n\n/**\n * my_application_new:\n *\n * Creates a new Flutter-based application.\n *\n * Returns: a new #MyApplication.\n */\nMyApplication* my_application_new();\n\n#endif  // FLUTTER_MY_APPLICATION_H_\n"
  },
  {
    "path": "linux/packaging/app.hiddify.com.appdata.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  Hiddify AppStream Metadata\n  Place this file at: linux/packaging/myappid.appdata.xml\n-->\n<component type=\"desktop-application\">\n  <id>app.hiddify.com</id>\n  <metadata_license>CC0-1.0</metadata_license>\n  <project_license>GPL-3.0-or-later</project_license>\n\n  <name>Hiddify</name>\n  <summary>Modern Proxy and VPN Manager for Linux</summary>\n\n  <developer_name>Hiddify</developer_name>\n  <update_contact>linux@hiddify.com</update_contact>\n\n  <description>\n    <p>\n      Hiddify is an advanced proxy and VPN client built for privacy and control. \n      It supports multiple backend protocols including V2Ray, Xray, Clash, and Sing-box, \n      providing flexibility and performance for all kinds of network configurations.\n    </p>\n    <p>\n      Designed with simplicity in mind, Hiddify helps users connect securely and \n      manage complex proxy configurations through a clean graphical interface.\n    </p>\n  </description>\n\n  <screenshots>\n    <screenshot type=\"default\">\n      <image>https://hiddify.com/assets/hiddify-next-mobile.svg</image>\n      <caption>Main Interface of Hiddify</caption>\n    </screenshot>\n  </screenshots>\n\n  <launchable type=\"desktop-id\">hiddify.desktop</launchable>\n\n  <icon type=\"stock\">hiddify</icon>\n\n  <categories>\n    <category>Network</category>\n  </categories>\n\n  <keywords>\n    <keyword>Hiddify</keyword>\n    <keyword>Proxy</keyword>\n    <keyword>VPN</keyword>\n    <keyword>V2Ray</keyword>\n    <keyword>Nekoray</keyword>\n    <keyword>Xray</keyword>\n    <keyword>Psiphon</keyword>\n    <keyword>OpenVPN</keyword>\n  </keywords>\n\n  <mime-types>\n    <mime-type>x-scheme-handler/hiddify</mime-type>\n    <mime-type>x-scheme-handler/v2ray</mime-type>\n    <mime-type>x-scheme-handler/v2rayn</mime-type>\n    <mime-type>x-scheme-handler/v2rayng</mime-type>\n    <mime-type>x-scheme-handler/clash</mime-type>\n    <mime-type>x-scheme-handler/clashmeta</mime-type>\n    <mime-type>x-scheme-handler/sing-box</mime-type>\n  </mime-types>\n\n  <url type=\"homepage\">https://hiddify.com</url>\n  <url type=\"bugtracker\">https://github.com/hiddify/hiddify-app/issues</url>\n  <url type=\"help\">https://docs.hiddify.com</url>\n\n  <provides>\n    <binary>hiddify</binary>\n  </provides>\n\n  <releases>\n    <release version=\"1.0.0\" date=\"2025-10-25\">\n      <description>\n        <p>Initial Linux release of Hiddify with multi-protocol support and modern UI.</p>\n      </description>\n    </release>\n  </releases>\n\n  <translation type=\"gettext\">hiddify</translation>\n\n  <custom>\n    <value key=\"PackageName\">hiddify</value>\n    <value key=\"Priority\">optional</value>\n    <value key=\"Section\">x11</value>\n    <value key=\"InstalledSize\">6604</value>\n    <value key=\"Essential\">false</value>\n  </custom>\n</component>"
  },
  {
    "path": "linux/packaging/appimage/AppRun",
    "content": "#!/bin/bash\n\ncd \"$(dirname \"$0\")\"\nexport LD_LIBRARY_PATH=usr/lib\n\n# Handles desktop integration:\n# 1. Copies app icons to ~/.local/share/icons\n# 2. Ensures icon theme index exists\n# 3. Creates a .desktop file pointing to this AppImage\n# 4. Skips if a system-wide installation (/usr/share/applications) is detected\ninstall_integration() {\n    if [[ -z \"$APPIMAGE\" ]]; then\n        return\n    fi\n\n    REAL_HOME=$(getent passwd \"$USER\" | cut -d: -f6)\n    \n    if [ -z \"$REAL_HOME\" ]; then\n        REAL_HOME=\"$HOME\"\n    fi\n\n    APP_NAME=\"hiddify\"\n    TARGET_DESKTOP=\"$REAL_HOME/.local/share/applications/hiddify.desktop\"\n    LOCAL_HICOLOR=\"$REAL_HOME/.local/share/icons/hicolor\"\n    \n    if [ ! -f \"$LOCAL_HICOLOR/index.theme\" ]; then\n        mkdir -p \"$LOCAL_HICOLOR\"\n        if [ -f \"/usr/share/icons/hicolor/index.theme\" ]; then\n            cp \"/usr/share/icons/hicolor/index.theme\" \"$LOCAL_HICOLOR/\"\n        else\n            echo -e \"[Icon Theme]\\nName=Hicolor\\nDirectories=128x128/apps,256x256/apps\" > \"$LOCAL_HICOLOR/index.theme\"\n        fi\n    fi\n\n    if [[ -f \"./hiddify.png\" ]]; then\n\n        mkdir -p \"$LOCAL_HICOLOR/128x128/apps\"\n        cp \"./hiddify.png\" \"$LOCAL_HICOLOR/128x128/apps/hiddify.png\"\n        \n        mkdir -p \"$LOCAL_HICOLOR/256x256/apps\"\n        cp \"./hiddify.png\" \"$LOCAL_HICOLOR/256x256/apps/hiddify.png\"\n        \n        gtk-update-icon-cache -f -t \"$LOCAL_HICOLOR\" 2>/dev/null || true\n    fi\n\n    if [ -f \"/usr/share/applications/hiddify.desktop\" ]; then\n        return\n    fi\n\n    mkdir -p \"$(dirname \"$TARGET_DESKTOP\")\"\n\n    cat > \"$TARGET_DESKTOP\" <<EOF\n[Desktop Entry]\nType=Application\nName=Hiddify\nExec=\"$APPIMAGE\"\nIcon=hiddify\nTerminal=false\nStartupWMClass=app.hiddify.com\nEOF\n\n    chmod +x \"$TARGET_DESKTOP\"\n    update-desktop-database \"$REAL_HOME/.local/share/applications\" 2>/dev/null || true\n}\n\n# Usage info\nshow_help() {\ncat << EOF\nUsage: ${0##*/} ...\nstart Hiddify or HiddifyCli, when no parameter is given, Hiddify is executed.\n    -v              show version\nEOF\n}\nshow_version() {\n    printf \"Hiddify version \"\n    jq .version <./data/flutter_assets/version.json\n}\n# Initialize variables:\nservice=0 #declare -i service\nOPTIND=1\n\n# Resetting OPTIND is necessary if getopts was used previously in the script.\n# It is a good idea to make OPTIND local if you process options in a function.\n\n# if no arg is provided, execute hiddify app\nif [[ $# == 0 ]];then \n    install_integration\n    exec ./hiddify\nelse\n\n# processing arguments\n\n    case $1 in\n        HiddifyCli)  \n            exec ./HiddifyCli ${@:3}\n            exit 0\n            ;;\n        h)\n            show_help\n            exit 0\n            ;;\n        v)  show_version\n            exit 0\n            ;;\n        *)\n            show_help >&2\n            exit 1\n            ;;\n    esac\n\n\n\nfi\n"
  },
  {
    "path": "linux/packaging/appimage/make_config.yaml",
    "content": "display_name: Hiddify\n\nicon: assets/images/source/ic_launcher_border.png\n\nkeywords:\n  - Hiddify\n  - Proxy\n  - VPN\n  - V2ray\n  - Nekoray\n  - Xray\n  - Psiphon\n  - OpenVPN\n\ngeneric_name: Hiddify\n\nactions:\n  - name: Start\n    label: start\n    arguments:\n      - --start\n  - name: Stop\n    label: stop\n    arguments:\n      - --stop\n\ncategories:\n  - Network\n\nstartup_notify: true\n\n# app_links setup for Linux\n# https://github.com/llfbandit/app_links/blob/master/doc/README_linux.md\nsupported_mime_type:\n  - x-scheme-handler/hiddify\n  - x-scheme-handler/v2ray\n  - x-scheme-handler/v2rayn\n  - x-scheme-handler/v2rayng\n  - x-scheme-handler/clash\n  - x-scheme-handler/clashmeta\n  - x-scheme-handler/sing-box\n\n# You can specify the shared libraries that you want to bundle with your app\n#\n# flutter_distributor automatically detects the shared libraries that your app\n# depends on, but you can also specify them manually here.\n#\n# The following example shows how to bundle the libcurl library with your app.\n#\n# include:\n#   - libcurl.so.4\ninclude: []\n\nmetainfo: linux/packaging/app.hiddify.com.appdata.xml"
  },
  {
    "path": "linux/packaging/deb/make_config.yaml",
    "content": "display_name: Hiddify\npackage_name: hiddify\nmaintainer:\n  name: hiddify\n  email: linux@hiddify.com\n\npriority: optional\nsection: x11\ninstalled_size: 6604\nessential: false\nicon: assets/images/source/ic_launcher_border.png\n\n# Post-installation tasks:\n# 1. Inject StartupWMClass into the system .desktop file for correct icon association\n# 2. Remove conflicting hiddify.desktop files from users' .local directories (cleanup AppImage artifacts)\n# 3. Update the desktop database to apply changes immediately\npostinstall_scripts:\n  - echo \"Setting up Hiddify...\"\n  - sudo sed -i '/^\\[Desktop Entry\\]/a StartupWMClass=app.hiddify.com' \"/usr/share/applications/hiddify.desktop\"\n  - echo \"Search and remove hiddify.desktop from .local\"\n  - for user_dir in /home/*; do if [ -f \"$user_dir/.local/share/applications/hiddify.desktop\" ]; then rm -f \"$user_dir/.local/share/applications/hiddify.desktop\"; echo \"Found and removed hiddify.desktop from $user_dir .local\"; fi; done\n  - update-desktop-database /usr/share/applications\n  - echo \"Hiddify is ready to use :)\"\n\n# Post-uninstallation tasks:\n# 1. Iterate through all user directories to remove Hiddify configuration and data\n# 2. Clean up root user data to ensure a clean removal\npostuninstall_scripts:\n  - echo \"Removing Hiddify user data...\"\n  - for user_dir in /home/*; do if [ -d \"$user_dir/.local/share/hiddify\" ]; then rm -rf \"$user_dir/.local/share/hiddify\"; echo \"Removed data from $user_dir\"; fi; done\n  - rm -rf /root/.local/share/hiddify\n  - echo \"Hiddify data cleanup complete.\"\n\nkeywords:\n  - Hiddify\n  - Proxy\n  - VPN\n  - V2ray\n  - Nekoray\n  - Xray\n  - Psiphon\n  - OpenVPN\n\ngeneric_name: Hiddify\n\ncategories:\n  - Network\n\nstartup_notify: true\n# app_links setup for Linux\n# https://github.com/llfbandit/app_links/blob/master/doc/README_linux.md\nsupported_mime_type:\n  - x-scheme-handler/hiddify\n  - x-scheme-handler/v2ray\n  - x-scheme-handler/v2rayn\n  - x-scheme-handler/v2rayng\n  - x-scheme-handler/clash\n  - x-scheme-handler/clashmeta\n  - x-scheme-handler/sing-box\n\nmetainfo: linux/packaging/app.hiddify.com.appdata.xml"
  },
  {
    "path": "linux/packaging/rpm/make_config.yaml",
    "content": "\n\n# <<<   RPM NOT SUPPORTED   >>>\n# We decided to remove RPM packaging for the following reasons:\n# - Flutter officially supports Debian-based systems only.\n# - Persistent issues with dependency linking.\n# - High maintenance overhead (requires Fedora environment setup).\n# - Successful builds do not guarantee runtime stability on Red Hat-based systems.\n\n\n# display_name: Hiddify\n# url: https://github.com/hiddify/hiddify-app\n# license: Other\n\n# packager: hiddify\n# packagerEmail: linux@hiddify.com\n\n# icon: assets/images/source/ic_launcher_border.png\n\n# keywords:\n#   - Hiddify\n#   - Proxy\n#   - VPN\n#   - V2ray\n#   - Nekoray\n#   - Xray\n#   - Psiphon\n#   - OpenVPN\n\n# generic_name: Hiddify\n\n# requires:\n#   - libayatana-appindicator-gtk3\n#   # - libcurl\n#   # - openssl\n\n# categories:\n#   - Network\n\n# startup_notify: true\n# # app_links setup for Linux\n# # https://github.com/llfbandit/app_links/blob/master/doc/README_linux.md\n# supported_mime_type:\n#   - x-scheme-handler/hiddify\n#   - x-scheme-handler/v2ray\n#   - x-scheme-handler/v2rayn\n#   - x-scheme-handler/v2rayng\n#   - x-scheme-handler/clash\n#   - x-scheme-handler/clashmeta\n#   - x-scheme-handler/sing-box\n"
  },
  {
    "path": "linux_deps.list",
    "content": "\n# ==============================================================\n#  ⚠️  USAGE: SHARED BY MAKEFILE & DOCKERFILE\n#  This list defines dependencies for both build environments.\n# ==============================================================\n\n# flutter sdk https://docs.flutter.dev/install/manual\ncurl git unzip xz-utils zip libglu1-mesa\n\n# linux development https://docs.flutter.dev/platform-integration/linux/setup\nclang cmake ninja-build pkg-config libgtk-3-dev libstdc++-12-dev\n\n# build & run https://docs.flutter.dev/platform-integration/linux/building\nlibgtk-3-0 libblkid1 liblzma5\n\n# fastforge rpm https://fastforge.dev/makers/rpm\nrpm patchelf\n\n# fastforge appimage https://fastforge.dev/makers/appimage\nlocate\n\n# tray_manager https://pub.dev/packages/tray_manager\nlibayatana-appindicator3-dev\n\n# for running .appimage\nfuse\n\n# Dockerfile\nmake sudo wget grep sed ca-certificates\n\n# Unknown Purpose\nlibcurl4-openssl-dev libglib2.0-dev file appstream"
  },
  {
    "path": "macos/.gitignore",
    "content": "# Flutter-related\n**/Flutter/ephemeral/\n**/Pods/\n\n# Xcode-related\n**/dgph\n**/xcuserdata/\n"
  },
  {
    "path": "macos/.stignore",
    "content": "**/Flutter/ephemeral/\n**/Pods/\n\n**/dgph\n**/xcuserdata/\n"
  },
  {
    "path": "macos/Flutter/Flutter-Debug.xcconfig",
    "content": "#include? \"Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"\n#include \"ephemeral/Flutter-Generated.xcconfig\"\n"
  },
  {
    "path": "macos/Flutter/Flutter-Release.xcconfig",
    "content": "#include? \"Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"\n#include \"ephemeral/Flutter-Generated.xcconfig\"\n"
  },
  {
    "path": "macos/Flutter/GeneratedPluginRegistrant.swift",
    "content": "//\n//  Generated file. Do not edit.\n//\n\nimport FlutterMacOS\nimport Foundation\n\nimport app_links\nimport device_info_plus\nimport dynamic_color\nimport file_picker\nimport in_app_review\nimport mobile_scanner\nimport network_info_plus\nimport package_info_plus\nimport path_provider_foundation\nimport screen_retriever_macos\nimport sentry_flutter\nimport share_plus\nimport shared_preferences_foundation\nimport sqlite3_flutter_libs\nimport tray_manager\nimport url_launcher_macos\nimport window_manager\n\nfunc RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {\n  AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: \"AppLinksMacosPlugin\"))\n  DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: \"DeviceInfoPlusMacosPlugin\"))\n  DynamicColorPlugin.register(with: registry.registrar(forPlugin: \"DynamicColorPlugin\"))\n  FilePickerPlugin.register(with: registry.registrar(forPlugin: \"FilePickerPlugin\"))\n  InAppReviewPlugin.register(with: registry.registrar(forPlugin: \"InAppReviewPlugin\"))\n  MobileScannerPlugin.register(with: registry.registrar(forPlugin: \"MobileScannerPlugin\"))\n  NetworkInfoPlusPlugin.register(with: registry.registrar(forPlugin: \"NetworkInfoPlusPlugin\"))\n  FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: \"FPPPackageInfoPlusPlugin\"))\n  PathProviderPlugin.register(with: registry.registrar(forPlugin: \"PathProviderPlugin\"))\n  ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: \"ScreenRetrieverMacosPlugin\"))\n  SentryFlutterPlugin.register(with: registry.registrar(forPlugin: \"SentryFlutterPlugin\"))\n  SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: \"SharePlusMacosPlugin\"))\n  SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: \"SharedPreferencesPlugin\"))\n  Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: \"Sqlite3FlutterLibsPlugin\"))\n  TrayManagerPlugin.register(with: registry.registrar(forPlugin: \"TrayManagerPlugin\"))\n  UrlLauncherPlugin.register(with: registry.registrar(forPlugin: \"UrlLauncherPlugin\"))\n  WindowManagerPlugin.register(with: registry.registrar(forPlugin: \"WindowManagerPlugin\"))\n}\n"
  },
  {
    "path": "macos/Podfile",
    "content": "platform :osx, '10.15'\n\n# CocoaPods analytics sends network stats synchronously affecting flutter build latency.\nENV['COCOAPODS_DISABLE_STATS'] = 'true'\n\nproject 'Runner', {\n  'Debug' => :debug,\n  'Profile' => :release,\n  'Release' => :release,\n}\n\ndef flutter_root\n  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)\n  unless File.exist?(generated_xcode_build_settings_path)\n    raise \"#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \\\"flutter pub get\\\" is executed first\"\n  end\n\n  File.foreach(generated_xcode_build_settings_path) do |line|\n    matches = line.match(/FLUTTER_ROOT\\=(.*)/)\n    return matches[1].strip if matches\n  end\n  raise \"FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \\\"flutter pub get\\\"\"\nend\n\nrequire File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)\n\nflutter_macos_podfile_setup\n\ntarget 'Runner' do\n  use_frameworks!\n  use_modular_headers!\n\n  flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))\n  target 'RunnerTests' do\n    inherit! :search_paths\n  end\nend\n\npost_install do |installer|\n  # Ensure pods also use the minimum deployment target set above\n  # https://stackoverflow.com/a/64385584/436422\n  puts 'Determining pod project minimum deployment target'\n\n  pods_project = installer.pods_project\n  deployment_target_key = 'MACOSX_DEPLOYMENT_TARGET'\n  deployment_targets = pods_project.build_configurations.map{ |config| config.build_settings[deployment_target_key] }\n  minimum_deployment_target = deployment_targets.min_by{ |version| Gem::Version.new(version) }\n\n  puts 'Minimal deployment target is ' + minimum_deployment_target\n  puts 'Setting each pod deployment target to ' + minimum_deployment_target\n\n  installer.pods_project.targets.each do |target|\n    flutter_additional_macos_build_settings(target)\n    target.build_configurations.each do |config|\n      config.build_settings[deployment_target_key] = minimum_deployment_target\n    end\n  end\nend\n"
  },
  {
    "path": "macos/Runner/AppDelegate.swift",
    "content": "import Cocoa\nimport FlutterMacOS\n\nimport UserNotifications\n@main\nclass AppDelegate: FlutterAppDelegate {\n  override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {\n    // https://github.com/leanflutter/window_manager/issues/214\n    return false\n  }\n  \n  override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {\n    return true\n  }\n  override func applicationDidFinishLaunching(_ aNotification: Notification) {\n        // Request notification authorization\n        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge]) { granted, error in\n            if let error = error {\n                print(\"Error requesting notification authorization: \\(error)\")\n            }\n        }\n    }\n\n\n  // // window manager restore from dock: https://leanflutter.dev/blog/click-dock-icon-to-restore-after-closing-the-window\n  // override func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {\n  //     if !flag {\n  //         for window in NSApp.windows {\n  //             if !window.isVisible {\n  //                 window.setIsVisible(true)\n  //             }\n  //             window.makeKeyAndOrderFront(self)\n  //             NSApp.activate(ignoringOtherApps: true)\n  //         }\n  //     }\n  //     return true\n  // }\n}\n"
  },
  {
    "path": "macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"filename\" : \"app-icon-16.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : \"16x16\"\n    },\n    {\n      \"filename\" : \"app-icon-16@2x.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"2x\",\n      \"size\" : \"16x16\"\n    },\n    {\n      \"filename\" : \"app-icon-32.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : \"32x32\"\n    },\n    {\n      \"filename\" : \"app-icon-32@2x.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"2x\",\n      \"size\" : \"32x32\"\n    },\n    {\n      \"filename\" : \"app-icon-128.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : \"128x128\"\n    },\n    {\n      \"filename\" : \"app-icon-128@2x.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"2x\",\n      \"size\" : \"128x128\"\n    },\n    {\n      \"filename\" : \"app-icon-256.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : \"256x256\"\n    },\n    {\n      \"filename\" : \"app-icon-256@2x.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"2x\",\n      \"size\" : \"256x256\"\n    },\n    {\n      \"filename\" : \"app-icon-512.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : \"512x512\"\n    },\n    {\n      \"filename\" : \"app-icon-512@2x.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"2x\",\n      \"size\" : \"512x512\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "macos/Runner/Base.lproj/MainMenu.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"22155\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"22155\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"NSApplication\">\n            <connections>\n                <outlet property=\"delegate\" destination=\"Voe-Tx-rLC\" id=\"GzC-gU-4Uq\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customObject id=\"Voe-Tx-rLC\" customClass=\"AppDelegate\" customModule=\"HiddifyNext\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"applicationMenu\" destination=\"uQy-DD-JDr\" id=\"XBo-yE-nKs\"/>\n                <outlet property=\"mainFlutterWindow\" destination=\"QvC-M9-y7g\" id=\"gIp-Ho-8D9\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"YLy-65-1bz\" customClass=\"NSFontManager\"/>\n        <menu title=\"Main Menu\" systemMenu=\"main\" id=\"AYu-sK-qS6\">\n            <items>\n                <menuItem title=\"APP_NAME\" id=\"1Xt-HY-uBw\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"APP_NAME\" systemMenu=\"apple\" id=\"uQy-DD-JDr\">\n                        <items>\n                            <menuItem title=\"About APP_NAME\" id=\"5kV-Vb-QxS\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"orderFrontStandardAboutPanel:\" target=\"-1\" id=\"Exp-CZ-Vem\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"VOq-y0-SEH\"/>\n                            <menuItem title=\"Preferences…\" keyEquivalent=\",\" id=\"BOF-NM-1cW\"/>\n                            <menuItem isSeparatorItem=\"YES\" id=\"wFC-TO-SCJ\"/>\n                            <menuItem title=\"Services\" id=\"NMo-om-nkz\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Services\" systemMenu=\"services\" id=\"hz9-B4-Xy5\"/>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"4je-JR-u6R\"/>\n                            <menuItem title=\"Hide APP_NAME\" keyEquivalent=\"h\" id=\"Olw-nP-bQN\">\n                                <connections>\n                                    <action selector=\"hide:\" target=\"-1\" id=\"PnN-Uc-m68\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Hide Others\" keyEquivalent=\"h\" id=\"Vdr-fp-XzO\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"hideOtherApplications:\" target=\"-1\" id=\"VT4-aY-XCT\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Show All\" id=\"Kd2-mp-pUS\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"unhideAllApplications:\" target=\"-1\" id=\"Dhg-Le-xox\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"kCx-OE-vgT\"/>\n                            <menuItem title=\"Quit APP_NAME\" keyEquivalent=\"q\" id=\"4sb-4s-VLi\">\n                                <connections>\n                                    <action selector=\"terminate:\" target=\"-1\" id=\"Te7-pn-YzF\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Edit\" id=\"5QF-Oa-p0T\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Edit\" id=\"W48-6f-4Dl\">\n                        <items>\n                            <menuItem title=\"Undo\" keyEquivalent=\"z\" id=\"dRJ-4n-Yzg\">\n                                <connections>\n                                    <action selector=\"undo:\" target=\"-1\" id=\"M6e-cu-g7V\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Redo\" keyEquivalent=\"Z\" id=\"6dh-zS-Vam\">\n                                <connections>\n                                    <action selector=\"redo:\" target=\"-1\" id=\"oIA-Rs-6OD\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"WRV-NI-Exz\"/>\n                            <menuItem title=\"Cut\" keyEquivalent=\"x\" id=\"uRl-iY-unG\">\n                                <connections>\n                                    <action selector=\"cut:\" target=\"-1\" id=\"YJe-68-I9s\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Copy\" keyEquivalent=\"c\" id=\"x3v-GG-iWU\">\n                                <connections>\n                                    <action selector=\"copy:\" target=\"-1\" id=\"G1f-GL-Joy\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Paste\" keyEquivalent=\"v\" id=\"gVA-U4-sdL\">\n                                <connections>\n                                    <action selector=\"paste:\" target=\"-1\" id=\"UvS-8e-Qdg\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Paste and Match Style\" keyEquivalent=\"V\" id=\"WeT-3V-zwk\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"pasteAsPlainText:\" target=\"-1\" id=\"cEh-KX-wJQ\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Delete\" id=\"pa3-QI-u2k\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"delete:\" target=\"-1\" id=\"0Mk-Ml-PaM\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Select All\" keyEquivalent=\"a\" id=\"Ruw-6m-B2m\">\n                                <connections>\n                                    <action selector=\"selectAll:\" target=\"-1\" id=\"VNm-Mi-diN\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"uyl-h8-XO2\"/>\n                            <menuItem title=\"Find\" id=\"4EN-yA-p0u\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Find\" id=\"1b7-l0-nxx\">\n                                    <items>\n                                        <menuItem title=\"Find…\" tag=\"1\" keyEquivalent=\"f\" id=\"Xz5-n4-O0W\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"cD7-Qs-BN4\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find and Replace…\" tag=\"12\" keyEquivalent=\"f\" id=\"YEy-JH-Tfz\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"WD3-Gg-5AJ\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find Next\" tag=\"2\" keyEquivalent=\"g\" id=\"q09-fT-Sye\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"NDo-RZ-v9R\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find Previous\" tag=\"3\" keyEquivalent=\"G\" id=\"OwM-mh-QMV\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"HOh-sY-3ay\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Use Selection for Find\" tag=\"7\" keyEquivalent=\"e\" id=\"buJ-ug-pKt\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"U76-nv-p5D\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Jump to Selection\" keyEquivalent=\"j\" id=\"S0p-oC-mLd\">\n                                            <connections>\n                                                <action selector=\"centerSelectionInVisibleArea:\" target=\"-1\" id=\"IOG-6D-g5B\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Spelling and Grammar\" id=\"Dv1-io-Yv7\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Spelling\" id=\"3IN-sU-3Bg\">\n                                    <items>\n                                        <menuItem title=\"Show Spelling and Grammar\" keyEquivalent=\":\" id=\"HFo-cy-zxI\">\n                                            <connections>\n                                                <action selector=\"showGuessPanel:\" target=\"-1\" id=\"vFj-Ks-hy3\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Check Document Now\" keyEquivalent=\";\" id=\"hz2-CU-CR7\">\n                                            <connections>\n                                                <action selector=\"checkSpelling:\" target=\"-1\" id=\"fz7-VC-reM\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"bNw-od-mp5\"/>\n                                        <menuItem title=\"Check Spelling While Typing\" id=\"rbD-Rh-wIN\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleContinuousSpellChecking:\" target=\"-1\" id=\"7w6-Qz-0kB\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Check Grammar With Spelling\" id=\"mK6-2p-4JG\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleGrammarChecking:\" target=\"-1\" id=\"muD-Qn-j4w\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Correct Spelling Automatically\" id=\"78Y-hA-62v\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticSpellingCorrection:\" target=\"-1\" id=\"2lM-Qi-WAP\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Substitutions\" id=\"9ic-FL-obx\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Substitutions\" id=\"FeM-D8-WVr\">\n                                    <items>\n                                        <menuItem title=\"Show Substitutions\" id=\"z6F-FW-3nz\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"orderFrontSubstitutionsPanel:\" target=\"-1\" id=\"oku-mr-iSq\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"gPx-C9-uUO\"/>\n                                        <menuItem title=\"Smart Copy/Paste\" id=\"9yt-4B-nSM\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleSmartInsertDelete:\" target=\"-1\" id=\"3IJ-Se-DZD\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Quotes\" id=\"hQb-2v-fYv\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticQuoteSubstitution:\" target=\"-1\" id=\"ptq-xd-QOA\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Dashes\" id=\"rgM-f4-ycn\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticDashSubstitution:\" target=\"-1\" id=\"oCt-pO-9gS\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Links\" id=\"cwL-P1-jid\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticLinkDetection:\" target=\"-1\" id=\"Gip-E3-Fov\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Data Detectors\" id=\"tRr-pd-1PS\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticDataDetection:\" target=\"-1\" id=\"R1I-Nq-Kbl\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Text Replacement\" id=\"HFQ-gK-NFA\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticTextReplacement:\" target=\"-1\" id=\"DvP-Fe-Py6\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Transformations\" id=\"2oI-Rn-ZJC\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Transformations\" id=\"c8a-y6-VQd\">\n                                    <items>\n                                        <menuItem title=\"Make Upper Case\" id=\"vmV-6d-7jI\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"uppercaseWord:\" target=\"-1\" id=\"sPh-Tk-edu\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Make Lower Case\" id=\"d9M-CD-aMd\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"lowercaseWord:\" target=\"-1\" id=\"iUZ-b5-hil\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Capitalize\" id=\"UEZ-Bs-lqG\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"capitalizeWord:\" target=\"-1\" id=\"26H-TL-nsh\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Speech\" id=\"xrE-MZ-jX0\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Speech\" id=\"3rS-ZA-NoH\">\n                                    <items>\n                                        <menuItem title=\"Start Speaking\" id=\"Ynk-f8-cLZ\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"startSpeaking:\" target=\"-1\" id=\"654-Ng-kyl\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Stop Speaking\" id=\"Oyz-dy-DGm\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"stopSpeaking:\" target=\"-1\" id=\"dX8-6p-jy9\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"View\" id=\"H8h-7b-M4v\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"View\" id=\"HyV-fh-RgO\">\n                        <items>\n                            <menuItem title=\"Enter Full Screen\" keyEquivalent=\"f\" id=\"4J7-dP-txa\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" control=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"toggleFullScreen:\" target=\"-1\" id=\"dU3-MA-1Rq\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Window\" id=\"aUF-d1-5bR\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Window\" systemMenu=\"window\" id=\"Td7-aD-5lo\">\n                        <items>\n                            <menuItem title=\"Minimize\" keyEquivalent=\"m\" id=\"OY7-WF-poV\">\n                                <connections>\n                                    <action selector=\"performMiniaturize:\" target=\"-1\" id=\"VwT-WD-YPe\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Zoom\" id=\"R4o-n2-Eq4\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"performZoom:\" target=\"-1\" id=\"DIl-cC-cCs\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"eu3-7i-yIM\"/>\n                            <menuItem title=\"Bring All to Front\" id=\"LE2-aR-0XJ\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"arrangeInFront:\" target=\"-1\" id=\"DRN-fu-gQh\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Help\" id=\"EPT-qC-fAb\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Help\" systemMenu=\"help\" id=\"rJ0-wn-3NY\"/>\n                </menuItem>\n            </items>\n            <point key=\"canvasLocation\" x=\"142\" y=\"-258\"/>\n        </menu>\n        <window title=\"APP_NAME\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" releasedWhenClosed=\"NO\" animationBehavior=\"default\" id=\"QvC-M9-y7g\" customClass=\"MainFlutterWindow\" customModule=\"HiddifyNext\" customModuleProvider=\"target\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\" miniaturizable=\"YES\" resizable=\"YES\"/>\n            <rect key=\"contentRect\" x=\"335\" y=\"390\" width=\"800\" height=\"600\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"1728\" height=\"1079\"/>\n            <view key=\"contentView\" wantsLayer=\"YES\" id=\"EiT-Mj-1SZ\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n            </view>\n        </window>\n    </objects>\n</document>\n"
  },
  {
    "path": "macos/Runner/Configs/AppInfo.xcconfig",
    "content": "// Application-level settings for the Runner target.\n//\n// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the\n// future. If not, the values below would default to using the project name when this becomes a\n// 'flutter create' template.\n\n// The application's name. By default this is also the title of the Flutter window.\nPRODUCT_NAME = Hiddify\n\n// The application's bundle identifier\nPRODUCT_BUNDLE_IDENTIFIER = app.hiddify.com\n\n// The copyright displayed in application information\nPRODUCT_COPYRIGHT = Copyright © 2023 hiddify.com. All rights reserved.\n"
  },
  {
    "path": "macos/Runner/Configs/Debug.xcconfig",
    "content": "#include \"../../Flutter/Flutter-Debug.xcconfig\"\n#include \"Warnings.xcconfig\"\n"
  },
  {
    "path": "macos/Runner/Configs/Release.xcconfig",
    "content": "#include \"../../Flutter/Flutter-Release.xcconfig\"\n#include \"Warnings.xcconfig\"\n"
  },
  {
    "path": "macos/Runner/Configs/Warnings.xcconfig",
    "content": "WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings\nGCC_WARN_UNDECLARED_SELECTOR = YES\nCLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES\nCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE\nCLANG_WARN__DUPLICATE_METHOD_MATCH = YES\nCLANG_WARN_PRAGMA_PACK = YES\nCLANG_WARN_STRICT_PROTOTYPES = YES\nCLANG_WARN_COMMA = YES\nGCC_WARN_STRICT_SELECTOR_MATCH = YES\nCLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES\nCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES\nGCC_WARN_SHADOW = YES\nCLANG_WARN_UNREACHABLE_CODE = YES\n"
  },
  {
    "path": "macos/Runner/DebugProfile.entitlements",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>com.apple.security.network.client</key>\n\t<true/>\n\t<!-- <key>com.apple.security.app-sandbox</key>\n\t<true/> -->\n\t<key>com.apple.security.app-sandbox</key>\n\t<false/>\n\t<key>com.apple.security.cs.allow-jit</key>\n\t<true/>\n\t<key>com.apple.security.network.server</key>\n\t<true/>\n\t\t<!-- <key>com.apple.developer.system-extension.install</key>\n\t\t<true/> -->\n<!-- \t\t\t\t\n\t<key>com.apple.developer.networking.networkextension</key>\n\t<array>\n\t\t\t\t<string>packet-tunnel-provider-systemextension</string>\n\t\t\t\t<string>app-proxy-provider-systemextension</string>\n\t\t\t\t<string>content-filter-provider-systemextension</string>\n\t\t\t\t<string>dns-proxy-systemextension</string> \n\t\t\t\t<string>dns-settings</string> \n\t\t\t\t<string>dns-proxy</string>\n\t\t\t\t<string>app-proxy-provider</string>\n\t\t\t\t<string>packet-tunnel-provider</string>\n\t</array>\n\t<key>com.apple.developer.networking.vpn.api</key>\n\t<string>allow-vpn</string> -->\n\n</dict>\n</plist>\n"
  },
  {
    "path": "macos/Runner/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIconFile</key>\n\t<string></string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(FLUTTER_BUILD_NAME)</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(FLUTTER_BUILD_NUMBER)</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>$(MACOSX_DEPLOYMENT_TARGET)</string>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>$(PRODUCT_COPYRIGHT)</string>\n\t<key>NSMainNibFile</key>\n\t<string>MainMenu</string>\n\t<key>CFBundleURLTypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>Editor</string>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string></string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>hiddify</string>\n\t\t\t\t<string>v2ray</string>\n\t\t\t\t<string>v2rayn</string>\n\t\t\t\t<string>v2rayng</string>\n\t\t\t\t<string>clash</string>\n\t\t\t\t<string>clashmeta</string>\n\t\t\t\t<string>sing-box</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n\t<key>NSPrincipalClass</key>\n\t<string>NSApplication</string>\n\t<key>CFBundleLocalizations</key>\n\t<array>\n\t\t<string>ar</string>\n\t\t<string>en</string>\n\t\t<string>es</string>\n\t\t<string>fa</string>\n\t\t<string>fr</string>\n\t\t<string>id</string>\n\t\t<string>pt-BR</string>\n\t\t<string>ru</string>\n\t\t<string>tr</string>\n\t\t<string>zh-CN</string>\n\t\t<string>zh-TW</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "macos/Runner/MainFlutterWindow.swift",
    "content": "import Cocoa\nimport FlutterMacOS\nimport window_manager\nimport LaunchAtLogin\n\nclass MainFlutterWindow: NSWindow {\n  override func awakeFromNib() {\n    let flutterViewController = FlutterViewController()\n    let windowFrame = self.frame\n    self.contentViewController = flutterViewController\n    self.setFrame(windowFrame, display: true)\n\n\n // Add FlutterMethodChannel platform code\n    FlutterMethodChannel(\n      name: \"launch_at_startup\", binaryMessenger: flutterViewController.engine.binaryMessenger\n    )\n    .setMethodCallHandler { (_ call: FlutterMethodCall, result: @escaping FlutterResult) in\n      switch call.method {\n      case \"launchAtStartupIsEnabled\":\n        result(LaunchAtLogin.isEnabled)\n      case \"launchAtStartupSetEnabled\":\n        if let arguments = call.arguments as? [String: Any] {\n          LaunchAtLogin.isEnabled = arguments[\"setEnabledValue\"] as! Bool\n        }\n        result(nil)\n      default:\n        result(FlutterMethodNotImplemented)\n      }\n    }\n    //\n    RegisterGeneratedPlugins(registry: flutterViewController)\n\n    super.awakeFromNib()\n  }\n\n  // window manager hidden at launch\n  override public func order(_ place: NSWindow.OrderingMode, relativeTo otherWin: Int) {\n    super.order(place, relativeTo: otherWin)\n    hiddenWindowAtLaunch()\n  }\n}\n"
  },
  {
    "path": "macos/Runner/Release.entitlements",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>com.apple.security.network.client</key>\n\t<true/>\n\t<!-- <key>com.apple.security.app-sandbox</key>\n\t<true/> -->\n\t<key>com.apple.security.app-sandbox</key>\n\t<false/>\n\t<key>com.apple.security.cs.allow-jit</key>\n\t<true/>\n\t<key>com.apple.security.network.server</key>\n\t<true/>\n\t\t<!-- <key>com.apple.developer.system-extension.install</key>\n\t\t<true/> -->\n<!-- \t\t\t\t\n\t<key>com.apple.developer.networking.networkextension</key>\n\t<array>\n\t\t\t\t<string>packet-tunnel-provider-systemextension</string>\n\t\t\t\t<string>app-proxy-provider-systemextension</string>\n\t\t\t\t<string>content-filter-provider-systemextension</string>\n\t\t\t\t<string>dns-proxy-systemextension</string> \n\t\t\t\t<string>dns-settings</string> \n\t\t\t\t<string>dns-proxy</string>\n\t\t\t\t<string>app-proxy-provider</string>\n\t\t\t\t<string>packet-tunnel-provider</string>\n\t</array>\n\t<key>com.apple.developer.networking.vpn.api</key>\n\t<string>allow-vpn</string> -->\n\n</dict>\n</plist>\n"
  },
  {
    "path": "macos/Runner.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 54;\n\tobjects = {\n\n/* Begin PBXAggregateTarget section */\n\t\t33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {\n\t\t\tisa = PBXAggregateTarget;\n\t\t\tbuildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget \"Flutter Assemble\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t33CC111E2044C6BF0003C045 /* ShellScript */,\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = \"Flutter Assemble\";\n\t\t\tproductName = FLX;\n\t\t};\n/* End PBXAggregateTarget section */\n\n/* Begin PBXBuildFile section */\n\t\t27D5969F2A92B6AB00E2BE2B /* hiddify-core.dylib in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 27D5969E2A92B6AB00E2BE2B /* hiddify-core.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };\n\t\t331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };\n\t\t335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };\n\t\t33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };\n\t\t33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };\n\t\t33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };\n\t\t33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };\n\t\t414949DC2CCE3D370069D5BA /* LaunchAtLogin in Frameworks */ = {isa = PBXBuildFile; productRef = 414949DB2CCE3D370069D5BA /* LaunchAtLogin */; };\n\t\tC2CEC907B854CCA50E3CB29E /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7774D5331C4F7054E7047DF2 /* Pods_RunnerTests.framework */; };\n\t\tFEE8413B259D2FDED8BE933A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1027315C9B3E3F83410A09 /* Pods_Runner.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 33CC10E52044A3C60003C045 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 33CC10EC2044A3C60003C045;\n\t\t\tremoteInfo = Runner;\n\t\t};\n\t\t33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 33CC10E52044A3C60003C045 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 33CC111A2044C6BA0003C045;\n\t\t\tremoteInfo = FLX;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t33CC110E2044A8840003C045 /* Bundle Framework */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 12;\n\t\t\tdstPath = Contents/Frameworks;\n\t\t\tdstSubfolderSpec = 1;\n\t\t\tfiles = (\n\t\t\t\t27D5969F2A92B6AB00E2BE2B /* hiddify-core.dylib in Bundle Framework */,\n\t\t\t);\n\t\t\tname = \"Bundle Framework\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t1A1027315C9B3E3F83410A09 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t1C05D6984C93FE0E5C9038D0 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-RunnerTests.release.xcconfig\"; path = \"Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t27D5969E2A92B6AB00E2BE2B /* hiddify-core.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = \"hiddify-core.dylib\"; path = \"../hiddify-core/bin/hiddify-core.dylib\"; sourceTree = \"<group>\"; };\n\t\t331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = \"<group>\"; };\n\t\t333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = \"<group>\"; };\n\t\t335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = \"<group>\"; };\n\t\t33CC10ED2044A3C60003C045 /* Hiddify.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Hiddify.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = \"<group>\"; };\n\t\t33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = \"<group>\"; };\n\t\t33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = \"<group>\"; };\n\t\t33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = \"Flutter-Debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = \"Flutter-Release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = \"Flutter-Generated.xcconfig\"; path = \"ephemeral/Flutter-Generated.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = \"<group>\"; };\n\t\t33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = \"<group>\"; };\n\t\t33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = \"<group>\"; };\n\t\t3E235443DDCB73D48BD2341C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner.debug.xcconfig\"; path = \"Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t49CD96905E177C4420930499 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner.profile.xcconfig\"; path = \"Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t7774D5331C4F7054E7047DF2 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = \"<group>\"; };\n\t\t7C0B4F177A93E89661E9B0CB /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-RunnerTests.debug.xcconfig\"; path = \"Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = \"<group>\"; };\n\t\tD96FD811DCD14FAF8EC1F071 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-RunnerTests.profile.xcconfig\"; path = \"Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tDBFB795F5E72237D66B9D391 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner.release.xcconfig\"; path = \"Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t331C80D2294CF70F00263BE5 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tC2CEC907B854CCA50E3CB29E /* Pods_RunnerTests.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t33CC10EA2044A3C60003C045 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t414949DC2CCE3D370069D5BA /* LaunchAtLogin in Frameworks */,\n\t\t\t\tFEE8413B259D2FDED8BE933A /* Pods_Runner.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t0B357514C188DFB6739B421A /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3E235443DDCB73D48BD2341C /* Pods-Runner.debug.xcconfig */,\n\t\t\t\tDBFB795F5E72237D66B9D391 /* Pods-Runner.release.xcconfig */,\n\t\t\t\t49CD96905E177C4420930499 /* Pods-Runner.profile.xcconfig */,\n\t\t\t\t7C0B4F177A93E89661E9B0CB /* Pods-RunnerTests.debug.xcconfig */,\n\t\t\t\t1C05D6984C93FE0E5C9038D0 /* Pods-RunnerTests.release.xcconfig */,\n\t\t\t\tD96FD811DCD14FAF8EC1F071 /* Pods-RunnerTests.profile.xcconfig */,\n\t\t\t);\n\t\t\tpath = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t331C80D6294CF71000263BE5 /* RunnerTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t331C80D7294CF71000263BE5 /* RunnerTests.swift */,\n\t\t\t);\n\t\t\tpath = RunnerTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t33BA886A226E78AF003329D5 /* Configs */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t33E5194F232828860026EE4D /* AppInfo.xcconfig */,\n\t\t\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */,\n\t\t\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */,\n\t\t\t\t333000ED22D3DE5D00554162 /* Warnings.xcconfig */,\n\t\t\t);\n\t\t\tpath = Configs;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t33CC10E42044A3C60003C045 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t27D5969E2A92B6AB00E2BE2B /* hiddify-core.dylib */,\n\t\t\t\t33FAB671232836740065AC1E /* Runner */,\n\t\t\t\t33CEB47122A05771004F2AC0 /* Flutter */,\n\t\t\t\t331C80D6294CF71000263BE5 /* RunnerTests */,\n\t\t\t\t33CC10EE2044A3C60003C045 /* Products */,\n\t\t\t\tD73912EC22F37F3D000D13A0 /* Frameworks */,\n\t\t\t\t0B357514C188DFB6739B421A /* Pods */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t33CC10EE2044A3C60003C045 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t33CC10ED2044A3C60003C045 /* Hiddify.app */,\n\t\t\t\t331C80D5294CF71000263BE5 /* RunnerTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t33CC11242044D66E0003C045 /* Resources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t33CC10F22044A3C60003C045 /* Assets.xcassets */,\n\t\t\t\t33CC10F42044A3C60003C045 /* MainMenu.xib */,\n\t\t\t\t33CC10F72044A3C60003C045 /* Info.plist */,\n\t\t\t);\n\t\t\tname = Resources;\n\t\t\tpath = ..;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t33CEB47122A05771004F2AC0 /* Flutter */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,\n\t\t\t\t33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,\n\t\t\t\t33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,\n\t\t\t\t33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,\n\t\t\t);\n\t\t\tpath = Flutter;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t33FAB671232836740065AC1E /* Runner */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t33CC10F02044A3C60003C045 /* AppDelegate.swift */,\n\t\t\t\t33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,\n\t\t\t\t33E51913231747F40026EE4D /* DebugProfile.entitlements */,\n\t\t\t\t33E51914231749380026EE4D /* Release.entitlements */,\n\t\t\t\t33CC11242044D66E0003C045 /* Resources */,\n\t\t\t\t33BA886A226E78AF003329D5 /* Configs */,\n\t\t\t);\n\t\t\tpath = Runner;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD73912EC22F37F3D000D13A0 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1A1027315C9B3E3F83410A09 /* Pods_Runner.framework */,\n\t\t\t\t7774D5331C4F7054E7047DF2 /* Pods_RunnerTests.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t331C80D4294CF70F00263BE5 /* RunnerTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget \"RunnerTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t33C54E5BCA15F9B3C8DDCCD2 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t331C80D1294CF70F00263BE5 /* Sources */,\n\t\t\t\t331C80D2294CF70F00263BE5 /* Frameworks */,\n\t\t\t\t331C80D3294CF70F00263BE5 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t331C80DA294CF71000263BE5 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = RunnerTests;\n\t\t\tproductName = RunnerTests;\n\t\t\tproductReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t33CC10EC2044A3C60003C045 /* Runner */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget \"Runner\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t40CB9C5051F17943B75EF3A9 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t33CC10E92044A3C60003C045 /* Sources */,\n\t\t\t\t33CC10EA2044A3C60003C045 /* Frameworks */,\n\t\t\t\t33CC10EB2044A3C60003C045 /* Resources */,\n\t\t\t\t33CC110E2044A8840003C045 /* Bundle Framework */,\n\t\t\t\t3399D490228B24CF009A79C7 /* ShellScript */,\n\t\t\t\tDDB714AFDEF721265C0C3AF7 /* [CP] Embed Pods Frameworks */,\n\t\t\t\t414949D92CCE3C2C0069D5BA /* ShellScript */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t33CC11202044C79F0003C045 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = Runner;\n\t\t\tpackageProductDependencies = (\n\t\t\t\t414949DB2CCE3D370069D5BA /* LaunchAtLogin */,\n\t\t\t);\n\t\t\tproductName = Runner;\n\t\t\tproductReference = 33CC10ED2044A3C60003C045 /* Hiddify.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t33CC10E52044A3C60003C045 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0920;\n\t\t\t\tLastUpgradeCheck = 1510;\n\t\t\t\tORGANIZATIONNAME = \"\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t331C80D4294CF70F00263BE5 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 14.0;\n\t\t\t\t\t\tTestTargetID = 33CC10EC2044A3C60003C045;\n\t\t\t\t\t};\n\t\t\t\t\t33CC10EC2044A3C60003C045 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 9.2;\n\t\t\t\t\t\tLastSwiftMigration = 1100;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t\tSystemCapabilities = {\n\t\t\t\t\t\t\tcom.apple.Sandbox = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t\t33CC111A2044C6BA0003C045 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 9.2;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject \"Runner\" */;\n\t\t\tcompatibilityVersion = \"Xcode 9.3\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 33CC10E42044A3C60003C045;\n\t\t\tpackageReferences = (\n\t\t\t\t414949DA2CCE3D370069D5BA /* XCRemoteSwiftPackageReference \"LaunchAtLogin-Legacy\" */,\n\t\t\t);\n\t\t\tproductRefGroup = 33CC10EE2044A3C60003C045 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t33CC10EC2044A3C60003C045 /* Runner */,\n\t\t\t\t331C80D4294CF70F00263BE5 /* RunnerTests */,\n\t\t\t\t33CC111A2044C6BA0003C045 /* Flutter Assemble */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t331C80D3294CF70F00263BE5 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t33CC10EB2044A3C60003C045 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,\n\t\t\t\t33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t3399D490228B24CF009A79C7 /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\talwaysOutOfDate = 1;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"echo \\\"$PRODUCT_NAME.app\\\" > \\\"$PROJECT_DIR\\\"/Flutter/ephemeral/.app_filename && \\\"$FLUTTER_ROOT\\\"/packages/flutter_tools/bin/macos_assemble.sh embed\\n\";\n\t\t};\n\t\t33C54E5BCA15F9B3C8DDCCD2 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t33CC111E2044C6BF0003C045 /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t\tFlutter/ephemeral/FlutterInputs.xcfilelist,\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\tFlutter/ephemeral/tripwire,\n\t\t\t);\n\t\t\toutputFileListPaths = (\n\t\t\t\tFlutter/ephemeral/FlutterOutputs.xcfilelist,\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"$FLUTTER_ROOT\\\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire\";\n\t\t};\n\t\t40CB9C5051F17943B75EF3A9 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t414949D92CCE3C2C0069D5BA /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\talwaysOutOfDate = 1;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"${BUILT_PRODUCTS_DIR}/LaunchAtLogin_LaunchAtLogin.bundle/Contents/Resources/copy-helper-swiftpm.sh\\n\";\n\t\t};\n\t\tDDB714AFDEF721265C0C3AF7 /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist\",\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t331C80D1294CF70F00263BE5 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t33CC10E92044A3C60003C045 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,\n\t\t\t\t33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,\n\t\t\t\t335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t331C80DA294CF71000263BE5 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 33CC10EC2044A3C60003C045 /* Runner */;\n\t\t\ttargetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */;\n\t\t};\n\t\t33CC11202044C79F0003C045 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;\n\t\t\ttargetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t33CC10F42044A3C60003C045 /* MainMenu.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t33CC10F52044A3C60003C045 /* Base */,\n\t\t\t);\n\t\t\tname = MainMenu.xib;\n\t\t\tpath = Runner;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t331C80DB294CF71000263BE5 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7C0B4F177A93E89661E9B0CB /* Pods-RunnerTests.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.hiddify.hiddify.RunnerTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/hiddify.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/hiddify\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t331C80DC294CF71000263BE5 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 1C05D6984C93FE0E5C9038D0 /* Pods-RunnerTests.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.hiddify.hiddify.RunnerTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/hiddify.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/hiddify\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t331C80DD294CF71000263BE5 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = D96FD811DCD14FAF8EC1F071 /* Pods-RunnerTests.profile.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.hiddify.hiddify.RunnerTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/hiddify.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/hiddify\";\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t338D0CE9231458BD00FA5F75 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t338D0CEA231458BD00FA5F75 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tINFOPLIST_KEY_CFBundleDisplayName = Hiddify;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t338D0CEB231458BD00FA5F75 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t33CC10F92044A3C60003C045 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t33CC10FA2044A3C60003C045 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t33CC10FC2044A3C60003C045 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tINFOPLIST_KEY_CFBundleDisplayName = Hiddify;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t33CC10FD2044A3C60003C045 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tINFOPLIST_KEY_CFBundleDisplayName = Hiddify;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t33CC111C2044C6BA0003C045 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t33CC111D2044C6BA0003C045 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget \"RunnerTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t331C80DB294CF71000263BE5 /* Debug */,\n\t\t\t\t331C80DC294CF71000263BE5 /* Release */,\n\t\t\t\t331C80DD294CF71000263BE5 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t33CC10E82044A3C60003C045 /* Build configuration list for PBXProject \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t33CC10F92044A3C60003C045 /* Debug */,\n\t\t\t\t33CC10FA2044A3C60003C045 /* Release */,\n\t\t\t\t338D0CE9231458BD00FA5F75 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t33CC10FC2044A3C60003C045 /* Debug */,\n\t\t\t\t33CC10FD2044A3C60003C045 /* Release */,\n\t\t\t\t338D0CEA231458BD00FA5F75 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget \"Flutter Assemble\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t33CC111C2044C6BA0003C045 /* Debug */,\n\t\t\t\t33CC111D2044C6BA0003C045 /* Release */,\n\t\t\t\t338D0CEB231458BD00FA5F75 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\n/* Begin XCRemoteSwiftPackageReference section */\n\t\t414949DA2CCE3D370069D5BA /* XCRemoteSwiftPackageReference \"LaunchAtLogin-Legacy\" */ = {\n\t\t\tisa = XCRemoteSwiftPackageReference;\n\t\t\trepositoryURL = \"https://github.com/sindresorhus/LaunchAtLogin-Legacy\";\n\t\t\trequirement = {\n\t\t\t\tbranch = main;\n\t\t\t\tkind = branch;\n\t\t\t};\n\t\t};\n/* End XCRemoteSwiftPackageReference section */\n\n/* Begin XCSwiftPackageProductDependency section */\n\t\t414949DB2CCE3D370069D5BA /* LaunchAtLogin */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tpackage = 414949DA2CCE3D370069D5BA /* XCRemoteSwiftPackageReference \"LaunchAtLogin-Legacy\" */;\n\t\t\tproductName = LaunchAtLogin;\n\t\t};\n/* End XCSwiftPackageProductDependency section */\n\t};\n\trootObject = 33CC10E52044A3C60003C045 /* Project object */;\n}\n"
  },
  {
    "path": "macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved",
    "content": "{\n  \"originHash\" : \"78526aafdff3d7bb5fccbf1f4499af4d3ea88e16e8819bf30db26c60f51192d8\",\n  \"pins\" : [\n    {\n      \"identity\" : \"launchatlogin-legacy\",\n      \"kind\" : \"remoteSourceControl\",\n      \"location\" : \"https://github.com/sindresorhus/LaunchAtLogin-Legacy\",\n      \"state\" : {\n        \"branch\" : \"main\",\n        \"revision\" : \"9a894d799269cb591037f9f9cb0961510d4dca81\"\n      }\n    }\n  ],\n  \"version\" : 2\n}\n"
  },
  {
    "path": "macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1510\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"33CC10EC2044A3C60003C045\"\n               BuildableName = \"Hiddify.app\"\n               BlueprintName = \"Runner\"\n               ReferencedContainer = \"container:Runner.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"33CC10EC2044A3C60003C045\"\n            BuildableName = \"Hiddify.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <Testables>\n         <TestableReference\n            skipped = \"NO\"\n            parallelizable = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"331C80D4294CF70F00263BE5\"\n               BuildableName = \"RunnerTests.xctest\"\n               BlueprintName = \"RunnerTests\"\n               ReferencedContainer = \"container:Runner.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      enableGPUValidationMode = \"1\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"33CC10EC2044A3C60003C045\"\n            BuildableName = \"Hiddify.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Profile\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"33CC10EC2044A3C60003C045\"\n            BuildableName = \"Hiddify.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "macos/Runner.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodeproj\">\n   </FileRef>\n   <FileRef\n      location = \"group:Pods/Pods.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved",
    "content": "{\n  \"originHash\" : \"78526aafdff3d7bb5fccbf1f4499af4d3ea88e16e8819bf30db26c60f51192d8\",\n  \"pins\" : [\n    {\n      \"identity\" : \"launchatlogin-legacy\",\n      \"kind\" : \"remoteSourceControl\",\n      \"location\" : \"https://github.com/sindresorhus/LaunchAtLogin-Legacy\",\n      \"state\" : {\n        \"branch\" : \"main\",\n        \"revision\" : \"9a894d799269cb591037f9f9cb0961510d4dca81\"\n      }\n    }\n  ],\n  \"version\" : 2\n}\n"
  },
  {
    "path": "macos/RunnerTests/RunnerTests.swift",
    "content": "import FlutterMacOS\nimport Cocoa\nimport XCTest\n\nclass RunnerTests: XCTestCase {\n\n  func testExample() {\n    // If you add code to the Runner application, consider adding tests here.\n    // See https://developer.apple.com/documentation/xctest for more information about using XCTest.\n  }\n\n}\n"
  },
  {
    "path": "macos/packaging/dmg/make_config.yaml",
    "content": "title: Hiddify\nbackground: \"background.png\"\nwindow:\n  size:\n    width: 600\n    height: 400\ncontents:\n  - x: 440\n    y: 230\n    type: link\n    path: \"/Applications\"\n  - x: 160\n    y: 230\n    type: file\n    path: Hiddify.app\n"
  },
  {
    "path": "macos/packaging/pkg/make_config.yaml",
    "content": "install-path: /Applications\n#sign-identity: \"Apple Development: app hiddify (VS8XK8XGMM)\"\n"
  },
  {
    "path": "project.inlang/project_id",
    "content": "33134c0ff949ed5f9d94c105afe0750868db4328feb5f504f9c62db06940f891"
  },
  {
    "path": "project.inlang/settings.json",
    "content": "{\n  \"$schema\": \"https://inlang.com/schema/project-settings\",\n  \"sourceLanguageTag\": \"en\",\n  \"languageTags\": [\n    \"en\",\n    \"ar\",\n    \"ckb-KUR\",\n    \"es\",\n    \"fa\",\n    \"fr\",\n    \"id\",\n    \"pt-BR\",\n    \"ru\",\n    \"tr\",\n    \"zh-CN\",\n    \"zh-TW\",\n    \"hi\"\n  ],\n  \"modules\": [\n    \"https://cdn.jsdelivr.net/npm/@inlang/plugin-i18next@4/dist/index.js\",\n    \"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@1/dist/index.js\",\n    \"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-identical-pattern@1/dist/index.js\",\n    \"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-without-source@1/dist/index.js\",\n    \"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@1/dist/index.js\",\n    \"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@latest/dist/index.js\"\n  ],\n  \"plugin.inlang.i18next\": {\n    \"pathPattern\": \"./assets/translations/strings_{languageTag}.i18n.json\",\n    \"variableReferencePattern\": [\n      \"@:\"\n    ]\n  }\n}"
  },
  {
    "path": "pubspec.yaml",
    "content": "name: hiddify\ndescription: Cross Platform Multi Protocol Proxy Frontend.\npublish_to: \"none\"\nversion: 4.1.2+40102\n\nenvironment:\n  sdk: ^3.10.4\n  # ! IMPORTANT !\n  # This SDK version is strictly required and must not be removed.\n  # It is parsed/grep-ed by Makefile and Dockerfile to configure the build environment.\n  # Ensure this matches the target Flutter version.\n  flutter: ^3.38.5\n  \ndependencies:\n  flutter:\n    sdk: flutter\n  flutter_localizations:\n    sdk: flutter\n  intl: ^0.20.2\n\n  # lucy_editor: ^1.0.5\n  # re_highlight: ^0.0.3\n  # json_editor_flutter: ^1.4.2\n\n  slang: ^4.8.1\n  slang_flutter: ^4.8.0\n  fpdart: ^1.1.0\n  freezed_annotation: ^2.4.1\n  json_annotation: ^4.9.0\n  hooks_riverpod: ^2.4.10\n  flutter_hooks: ^0.20.5\n  riverpod_annotation: ^2.3.4\n  rxdart: ^0.28.0\n  drift: ^2.21.0\n  drift_flutter: ^0.2.1\n  shared_preferences: ^2.5.2\n  # shared_preferences_android: ^2.4.8\n  dio: ^5.4.1\n  ffi: ^2.1.2\n  path_provider: ^2.1.1\n  mobile_scanner: ^7.2.0\n  # protocol_handler: ^0.2.0\n  flutter_native_splash: ^2.3.10\n  share_plus: ^10.1.0\n  window_manager: ^0.5.0\n  tray_manager: ^0.5.0\n  # get list of connected monitors (on Desktops), including their size and position\n  screen_retriever: ^0.2.0\n\n  package_info_plus: ^8.1.0\n\n  url_launcher: ^6.2.5\n  vclibs: ^0.1.2\n  launch_at_startup: ^0.5.1\n  sentry_flutter: ^8.14.0\n  sentry_dart_plugin: ^2.4.1\n  sqlite3_flutter_libs: ^0.5.28\n\n  combine: ^0.5.7\n  path: ^1.9.0\n  loggy: ^2.0.3\n  flutter_loggy: ^2.0.2\n  meta: ^1.15.0\n  dartx: ^1.2.0\n  uuid: ^4.3.3\n  tint: ^2.0.1\n  accessibility_tools: ^2.2.3\n  neat_periodic_task: ^2.0.1\n  watcher: ^1.1.0\n  go_router: ^16.2.4\n  flutter_animate: ^4.5.0\n  flutter_svg: ^2.0.10+1\n  gap: ^3.0.1\n  # percent_indicator_premium: ^0.0.2\n  sliver_tools: ^0.2.12\n  font_awesome_flutter: ^10.7.0\n  upgrader: ^11.3.0\n  toastification: ^2.3.0\n  version: ^3.0.2\n  posix: ^6.0.1\n  qr_flutter: ^4.1.0\n  flutter_displaymode: ^0.6.0\n  flutter_loggy_dio: ^3.1.0\n  dio_smart_retry: ^7.0.1\n  cupertino_http: ^2.0.1\n  dart_mappable: ^4.2.1\n  fluentui_system_icons: ^1.1.229\n  json_path: ^0.7.1\n  # permission_handler: ^11.3.0 # is not compatible with windows\n  #flutter_easy_permission: ^1.1.2\n  # flutter_easy_permission:\n  #   git: https://github.com/MichaelStH/flutter_easy_permission.git\n  in_app_review: ^2.0.10\n  # circle_flags: ^4.0.2\n  circle_flags:\n    git: https://github.com/hiddify-com/flutter_circle_flags.git\n  fixnum: ^1.1.0\n  grpc: ^4.0.1\n  bottom_navy_bar: ^6.1.0\n  # # for using protobuf install protoc from this link -> https://github.com/protocolbuffers/protobuf/releases\n  # # then add path to \"environment variable\" e.g. -> C:\\src\\protoc-28.3-win64\\bin\n  # # then active \"protoc_plugin\" by running this command -> dart pub global activate protoc_plugin\n  # # then add path to \"environment variable\" e.g. -> C:\\Users\\%USERPROFILE%\\AppData\\Local\\Pub\\Cache\\global_packages\\protoc_plugin\\bin\n  protobuf: ^2.0.0\n  dynamic_color: ^1.7.0\n  flutter_typeahead: ^5.0.1\n  # flutter_platform_widgets: ^7.0.1\n  simple_icons: ^10.1.3\n  animated_notch_bottom_bar: ^1.0.0\n  basic_utils: 5.7.0\n  showcaseview: 3.0.0\n  text_scroll: ^0.2.0\n  flutter_markdown_plus: ^1.0.6\n  # platform-specific  settings\n  # https://github.com/miguelpruivo/flutter_file_picker/wiki/Setup\n  file_picker: ^8.1.7\n  installed_apps: # ^1.5.2\n    git: https://github.com/VB10/installed_apps\n\n  # change case of text\n  # for example camelCase to snake_case\n  # helloWorld -> hello_worlds\n  recase: ^4.1.0\n  # Used for managing deep links on desktop platforms\n  # platform-specific settings\n  # https://github.com/llfbandit/app_links/tree/master/doc\n  app_links: ^6.4.0\n  # Used for registering custom schemes in the Windows registry\n  win32: ^5.12.0\n  # Working with Wifi(get LAN IP address)\n  # Web platform not supported\n  # platform-specific settings\n  network_info_plus: ^6.1.4\n  humanizer: ^3.0.1\n  dependency_validator: ^5.0.2\n\ndev_dependencies:\n  # flutter_test:\n  #   sdk: flutter\n  lint: ^2.3.0\n  build_web_compilers: ^4.0.11\n  build_runner: ^2.4.13\n  json_serializable: ^6.7.1\n  freezed: ^2.4.7\n  riverpod_generator: ^2.4.3\n  drift_dev: ^2.21.0\n  ffigen: ^19.1.0\n  slang_build_runner: ^4.4.0\n  flutter_gen_runner: ^5.4.0\n  dart_mappable_builder: ^4.2.1\n  # protoc_builder: ^0.4.1\n  # google_protobuf: ^3.20.1;\n\nflutter:\n  uses-material-design: true\n  assets:\n    # - assets/core/geoip.db\n    # - assets/core/geosite.db\n    - assets/images/logo.svg\n    - assets/images/tray_icon.ico\n    - assets/images/tray_icon.png\n    - assets/images/tray_icon_dark.ico\n    - assets/images/tray_icon_dark.png\n    - assets/images/tray_icon_connected.ico\n    - assets/images/tray_icon_connected.png\n    - assets/images/tray_icon_disconnected.ico\n    - assets/images/tray_icon_disconnected.png\n    - assets/images/connect_norouz.PNG\n    - assets/images/disconnect_norouz.PNG\n    - assets/images/world_map.png\n    - assets/images/source/ic_launcher_border.png\n\n  fonts:\n    - family: Shabnam\n      fonts:\n        - asset: assets/fonts/Shabnam.ttf\n    # - family: Roboto\n    #   fonts:\n    #     - asset: assets/fonts/Roboto.ttf\n    - family: Emoji\n      fonts:\n        - asset: assets/fonts/Emoji.ttf\n\nflutter_gen:\n  output: lib/gen/\n  integrations:\n    flutter_svg: true\n\nflutter_native_splash:\n  color: \"#ffffff\"\n  image: assets/images/source/ic_launcher_splash.png\n  android_gravity: center\n  android_12:\n    color: \"#ffffff\"\n    image: assets/images/source/ic_launcher_foreground.png\n\nffigen:\n  name: \"HiddifyCoreNativeLibrary\"\n  description: \"Bindings to Hiddify Core Library\"\n  output: \"lib/gen/hiddify_core_generated_bindings.dart\"\n  headers:\n    entry-points:\n      - \"hiddify-core/bin/desktop.h\"\n\nsentry:\n  upload_debug_symbols: true\n  upload_source_maps: true\n  upload_sources: true\n  log_level: info\n  ignore_missing: true\n"
  },
  {
    "path": "scripts/package_windows.ps1",
    "content": "New-Item -ItemType Directory -Force -Name \"dist\\tmp\"\nNew-Item -ItemType Directory -Force -Name \"out\"\n\n# windows setup\n# Get-ChildItem -Recurse -File -Path \"dist\" -Filter \"*windows-setup.exe\" | Copy-Item -Destination \"dist\\tmp\\hiddify-next-setup.exe\" -ErrorAction SilentlyContinue\n# Compress-Archive -Force -Path \"dist\\tmp\\hiddify-next-setup.exe\",\".github\\help\\mac-windows\\*.url\" -DestinationPath \"out\\hiddify-windows-x64-setup.zip\"\nGet-ChildItem -Recurse -File -Path \"dist\" -Filter \"*windows-setup.exe\" | Copy-Item -Destination \"out\\Hiddify-Windows-Setup-x64.exe\" -ErrorAction SilentlyContinue\nGet-ChildItem -Recurse -File -Path \"dist\" -Filter \"*windows.msix\" | Copy-Item -Destination \"out\\Hiddify-Windows-Setup-x64.msix\" -ErrorAction SilentlyContinue\n\n\n# windows portable\nxcopy \"build\\windows\\x64\\runner\\Release\" \"dist\\tmp\\hiddify-next\" /E/H/C/I/Y\nxcopy \".github\\help\\mac-windows\\*.url\" \"dist\\tmp\\hiddify-next\" /E/H/C/I/Y\nCompress-Archive -Force -Path \"dist\\tmp\\hiddify-next\" -DestinationPath \"out\\Hiddify-Windows-Portable-x64.zip\" -ErrorAction SilentlyContinue\n\nRemove-Item -Path \"$HOME\\.pub-cache\\git\\cache\\flutter_circle_flags*\" -Force -Recurse -ErrorAction SilentlyContinue\n\necho \"Done\""
  },
  {
    "path": "snap/gui/app_icon.desktop",
    "content": "[Desktop Entry]\nName=Flutter Linux App\nComment=Flutter Linux launcher icon\nExec=app_icon\nIcon=app_icon.png\nTerminal=false\nType=Application\nCategories=Entertainment;\n"
  },
  {
    "path": "test/core/utils/ip_utils_test.dart",
    "content": "import 'package:flutter_test/flutter_test.dart';\nimport 'package:hiddify/core/utils/ip_utils.dart';\n\nvoid main() {\n  group(\"obscureIp\", () {\n    test(\"Should obscure parts of ipv4\", () {\n      const ipv4 = \"1.1.1.1\";\n      final obscured = obscureIp(ipv4);\n      expect(obscured, \"1.*.*.1\");\n    });\n\n    test(\"Should obscure parts of full ipv6\", () {\n      const ipv6 = \"FEDC:BA98:7654:3210:FEDC:BA98:7654:3210\";\n      final obscured = obscureIp(ipv6);\n      expect(obscured, \"FEDC:****:****:****:****:****:****:****\");\n    });\n\n    test(\"Should obscure parts of ipv6\", () {\n      const ipv6 = \"::1\";\n      final obscured = obscureIp(ipv6);\n      expect(obscured, \"::*\");\n    });\n  });\n}\n"
  },
  {
    "path": "test/drift/db/generated/schema.dart",
    "content": "// dart format width=80\n// GENERATED CODE, DO NOT EDIT BY HAND.\n// ignore_for_file: type=lint\nimport 'package:drift/drift.dart';\nimport 'package:drift/internal/migrations.dart';\nimport 'schema_v1.dart' as v1;\nimport 'schema_v2.dart' as v2;\nimport 'schema_v3.dart' as v3;\nimport 'schema_v4.dart' as v4;\nimport 'schema_v5.dart' as v5;\n\nclass GeneratedHelper implements SchemaInstantiationHelper {\n  @override\n  GeneratedDatabase databaseForVersion(QueryExecutor db, int version) {\n    switch (version) {\n      case 1:\n        return v1.DatabaseAtV1(db);\n      case 2:\n        return v2.DatabaseAtV2(db);\n      case 3:\n        return v3.DatabaseAtV3(db);\n      case 4:\n        return v4.DatabaseAtV4(db);\n      case 5:\n        return v5.DatabaseAtV5(db);\n      default:\n        throw MissingSchemaException(version, versions);\n    }\n  }\n\n  static const versions = const [1, 2, 3, 4, 5];\n}\n"
  },
  {
    "path": "test/drift/db/generated/schema_v1.dart",
    "content": "// dart format width=80\n// GENERATED CODE, DO NOT EDIT BY HAND.\n// ignore_for_file: type=lint\nimport 'package:drift/drift.dart';\n\nclass ProfileEntries extends Table\n    with TableInfo<ProfileEntries, ProfileEntriesData> {\n  @override\n  final GeneratedDatabase attachedDatabase;\n  final String? _alias;\n  ProfileEntries(this.attachedDatabase, [this._alias]);\n  late final GeneratedColumn<String> id = GeneratedColumn<String>(\n    'id',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<bool> active = GeneratedColumn<bool>(\n    'active',\n    aliasedName,\n    false,\n    type: DriftSqlType.bool,\n    requiredDuringInsert: true,\n    defaultConstraints: GeneratedColumn.constraintIsAlways(\n      'CHECK (\"active\" IN (0, 1))',\n    ),\n  );\n  late final GeneratedColumn<String> name = GeneratedColumn<String>(\n    'name',\n    aliasedName,\n    false,\n    additionalChecks: GeneratedColumn.checkTextLength(minTextLength: 1),\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> url = GeneratedColumn<String>(\n    'url',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<DateTime> lastUpdate = GeneratedColumn<DateTime>(\n    'last_update',\n    aliasedName,\n    false,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<int> updateInterval = GeneratedColumn<int>(\n    'update_interval',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> upload = GeneratedColumn<int>(\n    'upload',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> download = GeneratedColumn<int>(\n    'download',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> total = GeneratedColumn<int>(\n    'total',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> expire = GeneratedColumn<DateTime>(\n    'expire',\n    aliasedName,\n    true,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> webPageUrl = GeneratedColumn<String>(\n    'web_page_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> supportUrl = GeneratedColumn<String>(\n    'support_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  @override\n  List<GeneratedColumn> get $columns => [\n    id,\n    active,\n    name,\n    url,\n    lastUpdate,\n    updateInterval,\n    upload,\n    download,\n    total,\n    expire,\n    webPageUrl,\n    supportUrl,\n  ];\n  @override\n  String get aliasedName => _alias ?? actualTableName;\n  @override\n  String get actualTableName => $name;\n  static const String $name = 'profile_entries';\n  @override\n  Set<GeneratedColumn> get $primaryKey => {id};\n  @override\n  ProfileEntriesData map(Map<String, dynamic> data, {String? tablePrefix}) {\n    final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';\n    return ProfileEntriesData(\n      id: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}id'],\n      )!,\n      active: attachedDatabase.typeMapping.read(\n        DriftSqlType.bool,\n        data['${effectivePrefix}active'],\n      )!,\n      name: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}name'],\n      )!,\n      url: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}url'],\n      )!,\n      lastUpdate: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}last_update'],\n      )!,\n      updateInterval: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}update_interval'],\n      ),\n      upload: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}upload'],\n      ),\n      download: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}download'],\n      ),\n      total: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}total'],\n      ),\n      expire: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}expire'],\n      ),\n      webPageUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}web_page_url'],\n      ),\n      supportUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}support_url'],\n      ),\n    );\n  }\n\n  @override\n  ProfileEntries createAlias(String alias) {\n    return ProfileEntries(attachedDatabase, alias);\n  }\n}\n\nclass ProfileEntriesData extends DataClass\n    implements Insertable<ProfileEntriesData> {\n  final String id;\n  final bool active;\n  final String name;\n  final String url;\n  final DateTime lastUpdate;\n  final int? updateInterval;\n  final int? upload;\n  final int? download;\n  final int? total;\n  final DateTime? expire;\n  final String? webPageUrl;\n  final String? supportUrl;\n  const ProfileEntriesData({\n    required this.id,\n    required this.active,\n    required this.name,\n    required this.url,\n    required this.lastUpdate,\n    this.updateInterval,\n    this.upload,\n    this.download,\n    this.total,\n    this.expire,\n    this.webPageUrl,\n    this.supportUrl,\n  });\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    map['id'] = Variable<String>(id);\n    map['active'] = Variable<bool>(active);\n    map['name'] = Variable<String>(name);\n    map['url'] = Variable<String>(url);\n    map['last_update'] = Variable<DateTime>(lastUpdate);\n    if (!nullToAbsent || updateInterval != null) {\n      map['update_interval'] = Variable<int>(updateInterval);\n    }\n    if (!nullToAbsent || upload != null) {\n      map['upload'] = Variable<int>(upload);\n    }\n    if (!nullToAbsent || download != null) {\n      map['download'] = Variable<int>(download);\n    }\n    if (!nullToAbsent || total != null) {\n      map['total'] = Variable<int>(total);\n    }\n    if (!nullToAbsent || expire != null) {\n      map['expire'] = Variable<DateTime>(expire);\n    }\n    if (!nullToAbsent || webPageUrl != null) {\n      map['web_page_url'] = Variable<String>(webPageUrl);\n    }\n    if (!nullToAbsent || supportUrl != null) {\n      map['support_url'] = Variable<String>(supportUrl);\n    }\n    return map;\n  }\n\n  ProfileEntriesCompanion toCompanion(bool nullToAbsent) {\n    return ProfileEntriesCompanion(\n      id: Value(id),\n      active: Value(active),\n      name: Value(name),\n      url: Value(url),\n      lastUpdate: Value(lastUpdate),\n      updateInterval: updateInterval == null && nullToAbsent\n          ? const Value.absent()\n          : Value(updateInterval),\n      upload: upload == null && nullToAbsent\n          ? const Value.absent()\n          : Value(upload),\n      download: download == null && nullToAbsent\n          ? const Value.absent()\n          : Value(download),\n      total: total == null && nullToAbsent\n          ? const Value.absent()\n          : Value(total),\n      expire: expire == null && nullToAbsent\n          ? const Value.absent()\n          : Value(expire),\n      webPageUrl: webPageUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(webPageUrl),\n      supportUrl: supportUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(supportUrl),\n    );\n  }\n\n  factory ProfileEntriesData.fromJson(\n    Map<String, dynamic> json, {\n    ValueSerializer? serializer,\n  }) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return ProfileEntriesData(\n      id: serializer.fromJson<String>(json['id']),\n      active: serializer.fromJson<bool>(json['active']),\n      name: serializer.fromJson<String>(json['name']),\n      url: serializer.fromJson<String>(json['url']),\n      lastUpdate: serializer.fromJson<DateTime>(json['lastUpdate']),\n      updateInterval: serializer.fromJson<int?>(json['updateInterval']),\n      upload: serializer.fromJson<int?>(json['upload']),\n      download: serializer.fromJson<int?>(json['download']),\n      total: serializer.fromJson<int?>(json['total']),\n      expire: serializer.fromJson<DateTime?>(json['expire']),\n      webPageUrl: serializer.fromJson<String?>(json['webPageUrl']),\n      supportUrl: serializer.fromJson<String?>(json['supportUrl']),\n    );\n  }\n  @override\n  Map<String, dynamic> toJson({ValueSerializer? serializer}) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return <String, dynamic>{\n      'id': serializer.toJson<String>(id),\n      'active': serializer.toJson<bool>(active),\n      'name': serializer.toJson<String>(name),\n      'url': serializer.toJson<String>(url),\n      'lastUpdate': serializer.toJson<DateTime>(lastUpdate),\n      'updateInterval': serializer.toJson<int?>(updateInterval),\n      'upload': serializer.toJson<int?>(upload),\n      'download': serializer.toJson<int?>(download),\n      'total': serializer.toJson<int?>(total),\n      'expire': serializer.toJson<DateTime?>(expire),\n      'webPageUrl': serializer.toJson<String?>(webPageUrl),\n      'supportUrl': serializer.toJson<String?>(supportUrl),\n    };\n  }\n\n  ProfileEntriesData copyWith({\n    String? id,\n    bool? active,\n    String? name,\n    String? url,\n    DateTime? lastUpdate,\n    Value<int?> updateInterval = const Value.absent(),\n    Value<int?> upload = const Value.absent(),\n    Value<int?> download = const Value.absent(),\n    Value<int?> total = const Value.absent(),\n    Value<DateTime?> expire = const Value.absent(),\n    Value<String?> webPageUrl = const Value.absent(),\n    Value<String?> supportUrl = const Value.absent(),\n  }) => ProfileEntriesData(\n    id: id ?? this.id,\n    active: active ?? this.active,\n    name: name ?? this.name,\n    url: url ?? this.url,\n    lastUpdate: lastUpdate ?? this.lastUpdate,\n    updateInterval: updateInterval.present\n        ? updateInterval.value\n        : this.updateInterval,\n    upload: upload.present ? upload.value : this.upload,\n    download: download.present ? download.value : this.download,\n    total: total.present ? total.value : this.total,\n    expire: expire.present ? expire.value : this.expire,\n    webPageUrl: webPageUrl.present ? webPageUrl.value : this.webPageUrl,\n    supportUrl: supportUrl.present ? supportUrl.value : this.supportUrl,\n  );\n  ProfileEntriesData copyWithCompanion(ProfileEntriesCompanion data) {\n    return ProfileEntriesData(\n      id: data.id.present ? data.id.value : this.id,\n      active: data.active.present ? data.active.value : this.active,\n      name: data.name.present ? data.name.value : this.name,\n      url: data.url.present ? data.url.value : this.url,\n      lastUpdate: data.lastUpdate.present\n          ? data.lastUpdate.value\n          : this.lastUpdate,\n      updateInterval: data.updateInterval.present\n          ? data.updateInterval.value\n          : this.updateInterval,\n      upload: data.upload.present ? data.upload.value : this.upload,\n      download: data.download.present ? data.download.value : this.download,\n      total: data.total.present ? data.total.value : this.total,\n      expire: data.expire.present ? data.expire.value : this.expire,\n      webPageUrl: data.webPageUrl.present\n          ? data.webPageUrl.value\n          : this.webPageUrl,\n      supportUrl: data.supportUrl.present\n          ? data.supportUrl.value\n          : this.supportUrl,\n    );\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('ProfileEntriesData(')\n          ..write('id: $id, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('url: $url, ')\n          ..write('lastUpdate: $lastUpdate, ')\n          ..write('updateInterval: $updateInterval, ')\n          ..write('upload: $upload, ')\n          ..write('download: $download, ')\n          ..write('total: $total, ')\n          ..write('expire: $expire, ')\n          ..write('webPageUrl: $webPageUrl, ')\n          ..write('supportUrl: $supportUrl')\n          ..write(')'))\n        .toString();\n  }\n\n  @override\n  int get hashCode => Object.hash(\n    id,\n    active,\n    name,\n    url,\n    lastUpdate,\n    updateInterval,\n    upload,\n    download,\n    total,\n    expire,\n    webPageUrl,\n    supportUrl,\n  );\n  @override\n  bool operator ==(Object other) =>\n      identical(this, other) ||\n      (other is ProfileEntriesData &&\n          other.id == this.id &&\n          other.active == this.active &&\n          other.name == this.name &&\n          other.url == this.url &&\n          other.lastUpdate == this.lastUpdate &&\n          other.updateInterval == this.updateInterval &&\n          other.upload == this.upload &&\n          other.download == this.download &&\n          other.total == this.total &&\n          other.expire == this.expire &&\n          other.webPageUrl == this.webPageUrl &&\n          other.supportUrl == this.supportUrl);\n}\n\nclass ProfileEntriesCompanion extends UpdateCompanion<ProfileEntriesData> {\n  final Value<String> id;\n  final Value<bool> active;\n  final Value<String> name;\n  final Value<String> url;\n  final Value<DateTime> lastUpdate;\n  final Value<int?> updateInterval;\n  final Value<int?> upload;\n  final Value<int?> download;\n  final Value<int?> total;\n  final Value<DateTime?> expire;\n  final Value<String?> webPageUrl;\n  final Value<String?> supportUrl;\n  final Value<int> rowid;\n  const ProfileEntriesCompanion({\n    this.id = const Value.absent(),\n    this.active = const Value.absent(),\n    this.name = const Value.absent(),\n    this.url = const Value.absent(),\n    this.lastUpdate = const Value.absent(),\n    this.updateInterval = const Value.absent(),\n    this.upload = const Value.absent(),\n    this.download = const Value.absent(),\n    this.total = const Value.absent(),\n    this.expire = const Value.absent(),\n    this.webPageUrl = const Value.absent(),\n    this.supportUrl = const Value.absent(),\n    this.rowid = const Value.absent(),\n  });\n  ProfileEntriesCompanion.insert({\n    required String id,\n    required bool active,\n    required String name,\n    required String url,\n    required DateTime lastUpdate,\n    this.updateInterval = const Value.absent(),\n    this.upload = const Value.absent(),\n    this.download = const Value.absent(),\n    this.total = const Value.absent(),\n    this.expire = const Value.absent(),\n    this.webPageUrl = const Value.absent(),\n    this.supportUrl = const Value.absent(),\n    this.rowid = const Value.absent(),\n  }) : id = Value(id),\n       active = Value(active),\n       name = Value(name),\n       url = Value(url),\n       lastUpdate = Value(lastUpdate);\n  static Insertable<ProfileEntriesData> custom({\n    Expression<String>? id,\n    Expression<bool>? active,\n    Expression<String>? name,\n    Expression<String>? url,\n    Expression<DateTime>? lastUpdate,\n    Expression<int>? updateInterval,\n    Expression<int>? upload,\n    Expression<int>? download,\n    Expression<int>? total,\n    Expression<DateTime>? expire,\n    Expression<String>? webPageUrl,\n    Expression<String>? supportUrl,\n    Expression<int>? rowid,\n  }) {\n    return RawValuesInsertable({\n      if (id != null) 'id': id,\n      if (active != null) 'active': active,\n      if (name != null) 'name': name,\n      if (url != null) 'url': url,\n      if (lastUpdate != null) 'last_update': lastUpdate,\n      if (updateInterval != null) 'update_interval': updateInterval,\n      if (upload != null) 'upload': upload,\n      if (download != null) 'download': download,\n      if (total != null) 'total': total,\n      if (expire != null) 'expire': expire,\n      if (webPageUrl != null) 'web_page_url': webPageUrl,\n      if (supportUrl != null) 'support_url': supportUrl,\n      if (rowid != null) 'rowid': rowid,\n    });\n  }\n\n  ProfileEntriesCompanion copyWith({\n    Value<String>? id,\n    Value<bool>? active,\n    Value<String>? name,\n    Value<String>? url,\n    Value<DateTime>? lastUpdate,\n    Value<int?>? updateInterval,\n    Value<int?>? upload,\n    Value<int?>? download,\n    Value<int?>? total,\n    Value<DateTime?>? expire,\n    Value<String?>? webPageUrl,\n    Value<String?>? supportUrl,\n    Value<int>? rowid,\n  }) {\n    return ProfileEntriesCompanion(\n      id: id ?? this.id,\n      active: active ?? this.active,\n      name: name ?? this.name,\n      url: url ?? this.url,\n      lastUpdate: lastUpdate ?? this.lastUpdate,\n      updateInterval: updateInterval ?? this.updateInterval,\n      upload: upload ?? this.upload,\n      download: download ?? this.download,\n      total: total ?? this.total,\n      expire: expire ?? this.expire,\n      webPageUrl: webPageUrl ?? this.webPageUrl,\n      supportUrl: supportUrl ?? this.supportUrl,\n      rowid: rowid ?? this.rowid,\n    );\n  }\n\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    if (id.present) {\n      map['id'] = Variable<String>(id.value);\n    }\n    if (active.present) {\n      map['active'] = Variable<bool>(active.value);\n    }\n    if (name.present) {\n      map['name'] = Variable<String>(name.value);\n    }\n    if (url.present) {\n      map['url'] = Variable<String>(url.value);\n    }\n    if (lastUpdate.present) {\n      map['last_update'] = Variable<DateTime>(lastUpdate.value);\n    }\n    if (updateInterval.present) {\n      map['update_interval'] = Variable<int>(updateInterval.value);\n    }\n    if (upload.present) {\n      map['upload'] = Variable<int>(upload.value);\n    }\n    if (download.present) {\n      map['download'] = Variable<int>(download.value);\n    }\n    if (total.present) {\n      map['total'] = Variable<int>(total.value);\n    }\n    if (expire.present) {\n      map['expire'] = Variable<DateTime>(expire.value);\n    }\n    if (webPageUrl.present) {\n      map['web_page_url'] = Variable<String>(webPageUrl.value);\n    }\n    if (supportUrl.present) {\n      map['support_url'] = Variable<String>(supportUrl.value);\n    }\n    if (rowid.present) {\n      map['rowid'] = Variable<int>(rowid.value);\n    }\n    return map;\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('ProfileEntriesCompanion(')\n          ..write('id: $id, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('url: $url, ')\n          ..write('lastUpdate: $lastUpdate, ')\n          ..write('updateInterval: $updateInterval, ')\n          ..write('upload: $upload, ')\n          ..write('download: $download, ')\n          ..write('total: $total, ')\n          ..write('expire: $expire, ')\n          ..write('webPageUrl: $webPageUrl, ')\n          ..write('supportUrl: $supportUrl, ')\n          ..write('rowid: $rowid')\n          ..write(')'))\n        .toString();\n  }\n}\n\nclass DatabaseAtV1 extends GeneratedDatabase {\n  DatabaseAtV1(QueryExecutor e) : super(e);\n  late final ProfileEntries profileEntries = ProfileEntries(this);\n  @override\n  Iterable<TableInfo<Table, Object?>> get allTables =>\n      allSchemaEntities.whereType<TableInfo<Table, Object?>>();\n  @override\n  List<DatabaseSchemaEntity> get allSchemaEntities => [profileEntries];\n  @override\n  int get schemaVersion => 1;\n  @override\n  DriftDatabaseOptions get options =>\n      const DriftDatabaseOptions(storeDateTimeAsText: true);\n}\n"
  },
  {
    "path": "test/drift/db/generated/schema_v2.dart",
    "content": "// dart format width=80\n// GENERATED CODE, DO NOT EDIT BY HAND.\n// ignore_for_file: type=lint\nimport 'package:drift/drift.dart';\n\nclass ProfileEntries extends Table\n    with TableInfo<ProfileEntries, ProfileEntriesData> {\n  @override\n  final GeneratedDatabase attachedDatabase;\n  final String? _alias;\n  ProfileEntries(this.attachedDatabase, [this._alias]);\n  late final GeneratedColumn<String> id = GeneratedColumn<String>(\n    'id',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> type = GeneratedColumn<String>(\n    'type',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<bool> active = GeneratedColumn<bool>(\n    'active',\n    aliasedName,\n    false,\n    type: DriftSqlType.bool,\n    requiredDuringInsert: true,\n    defaultConstraints: GeneratedColumn.constraintIsAlways(\n      'CHECK (\"active\" IN (0, 1))',\n    ),\n  );\n  late final GeneratedColumn<String> name = GeneratedColumn<String>(\n    'name',\n    aliasedName,\n    false,\n    additionalChecks: GeneratedColumn.checkTextLength(minTextLength: 1),\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> url = GeneratedColumn<String>(\n    'url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> lastUpdate = GeneratedColumn<DateTime>(\n    'last_update',\n    aliasedName,\n    false,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<int> updateInterval = GeneratedColumn<int>(\n    'update_interval',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> upload = GeneratedColumn<int>(\n    'upload',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> download = GeneratedColumn<int>(\n    'download',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> total = GeneratedColumn<int>(\n    'total',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> expire = GeneratedColumn<DateTime>(\n    'expire',\n    aliasedName,\n    true,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> webPageUrl = GeneratedColumn<String>(\n    'web_page_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> supportUrl = GeneratedColumn<String>(\n    'support_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  @override\n  List<GeneratedColumn> get $columns => [\n    id,\n    type,\n    active,\n    name,\n    url,\n    lastUpdate,\n    updateInterval,\n    upload,\n    download,\n    total,\n    expire,\n    webPageUrl,\n    supportUrl,\n  ];\n  @override\n  String get aliasedName => _alias ?? actualTableName;\n  @override\n  String get actualTableName => $name;\n  static const String $name = 'profile_entries';\n  @override\n  Set<GeneratedColumn> get $primaryKey => {id};\n  @override\n  ProfileEntriesData map(Map<String, dynamic> data, {String? tablePrefix}) {\n    final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';\n    return ProfileEntriesData(\n      id: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}id'],\n      )!,\n      type: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}type'],\n      )!,\n      active: attachedDatabase.typeMapping.read(\n        DriftSqlType.bool,\n        data['${effectivePrefix}active'],\n      )!,\n      name: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}name'],\n      )!,\n      url: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}url'],\n      ),\n      lastUpdate: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}last_update'],\n      )!,\n      updateInterval: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}update_interval'],\n      ),\n      upload: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}upload'],\n      ),\n      download: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}download'],\n      ),\n      total: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}total'],\n      ),\n      expire: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}expire'],\n      ),\n      webPageUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}web_page_url'],\n      ),\n      supportUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}support_url'],\n      ),\n    );\n  }\n\n  @override\n  ProfileEntries createAlias(String alias) {\n    return ProfileEntries(attachedDatabase, alias);\n  }\n}\n\nclass ProfileEntriesData extends DataClass\n    implements Insertable<ProfileEntriesData> {\n  final String id;\n  final String type;\n  final bool active;\n  final String name;\n  final String? url;\n  final DateTime lastUpdate;\n  final int? updateInterval;\n  final int? upload;\n  final int? download;\n  final int? total;\n  final DateTime? expire;\n  final String? webPageUrl;\n  final String? supportUrl;\n  const ProfileEntriesData({\n    required this.id,\n    required this.type,\n    required this.active,\n    required this.name,\n    this.url,\n    required this.lastUpdate,\n    this.updateInterval,\n    this.upload,\n    this.download,\n    this.total,\n    this.expire,\n    this.webPageUrl,\n    this.supportUrl,\n  });\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    map['id'] = Variable<String>(id);\n    map['type'] = Variable<String>(type);\n    map['active'] = Variable<bool>(active);\n    map['name'] = Variable<String>(name);\n    if (!nullToAbsent || url != null) {\n      map['url'] = Variable<String>(url);\n    }\n    map['last_update'] = Variable<DateTime>(lastUpdate);\n    if (!nullToAbsent || updateInterval != null) {\n      map['update_interval'] = Variable<int>(updateInterval);\n    }\n    if (!nullToAbsent || upload != null) {\n      map['upload'] = Variable<int>(upload);\n    }\n    if (!nullToAbsent || download != null) {\n      map['download'] = Variable<int>(download);\n    }\n    if (!nullToAbsent || total != null) {\n      map['total'] = Variable<int>(total);\n    }\n    if (!nullToAbsent || expire != null) {\n      map['expire'] = Variable<DateTime>(expire);\n    }\n    if (!nullToAbsent || webPageUrl != null) {\n      map['web_page_url'] = Variable<String>(webPageUrl);\n    }\n    if (!nullToAbsent || supportUrl != null) {\n      map['support_url'] = Variable<String>(supportUrl);\n    }\n    return map;\n  }\n\n  ProfileEntriesCompanion toCompanion(bool nullToAbsent) {\n    return ProfileEntriesCompanion(\n      id: Value(id),\n      type: Value(type),\n      active: Value(active),\n      name: Value(name),\n      url: url == null && nullToAbsent ? const Value.absent() : Value(url),\n      lastUpdate: Value(lastUpdate),\n      updateInterval: updateInterval == null && nullToAbsent\n          ? const Value.absent()\n          : Value(updateInterval),\n      upload: upload == null && nullToAbsent\n          ? const Value.absent()\n          : Value(upload),\n      download: download == null && nullToAbsent\n          ? const Value.absent()\n          : Value(download),\n      total: total == null && nullToAbsent\n          ? const Value.absent()\n          : Value(total),\n      expire: expire == null && nullToAbsent\n          ? const Value.absent()\n          : Value(expire),\n      webPageUrl: webPageUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(webPageUrl),\n      supportUrl: supportUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(supportUrl),\n    );\n  }\n\n  factory ProfileEntriesData.fromJson(\n    Map<String, dynamic> json, {\n    ValueSerializer? serializer,\n  }) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return ProfileEntriesData(\n      id: serializer.fromJson<String>(json['id']),\n      type: serializer.fromJson<String>(json['type']),\n      active: serializer.fromJson<bool>(json['active']),\n      name: serializer.fromJson<String>(json['name']),\n      url: serializer.fromJson<String?>(json['url']),\n      lastUpdate: serializer.fromJson<DateTime>(json['lastUpdate']),\n      updateInterval: serializer.fromJson<int?>(json['updateInterval']),\n      upload: serializer.fromJson<int?>(json['upload']),\n      download: serializer.fromJson<int?>(json['download']),\n      total: serializer.fromJson<int?>(json['total']),\n      expire: serializer.fromJson<DateTime?>(json['expire']),\n      webPageUrl: serializer.fromJson<String?>(json['webPageUrl']),\n      supportUrl: serializer.fromJson<String?>(json['supportUrl']),\n    );\n  }\n  @override\n  Map<String, dynamic> toJson({ValueSerializer? serializer}) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return <String, dynamic>{\n      'id': serializer.toJson<String>(id),\n      'type': serializer.toJson<String>(type),\n      'active': serializer.toJson<bool>(active),\n      'name': serializer.toJson<String>(name),\n      'url': serializer.toJson<String?>(url),\n      'lastUpdate': serializer.toJson<DateTime>(lastUpdate),\n      'updateInterval': serializer.toJson<int?>(updateInterval),\n      'upload': serializer.toJson<int?>(upload),\n      'download': serializer.toJson<int?>(download),\n      'total': serializer.toJson<int?>(total),\n      'expire': serializer.toJson<DateTime?>(expire),\n      'webPageUrl': serializer.toJson<String?>(webPageUrl),\n      'supportUrl': serializer.toJson<String?>(supportUrl),\n    };\n  }\n\n  ProfileEntriesData copyWith({\n    String? id,\n    String? type,\n    bool? active,\n    String? name,\n    Value<String?> url = const Value.absent(),\n    DateTime? lastUpdate,\n    Value<int?> updateInterval = const Value.absent(),\n    Value<int?> upload = const Value.absent(),\n    Value<int?> download = const Value.absent(),\n    Value<int?> total = const Value.absent(),\n    Value<DateTime?> expire = const Value.absent(),\n    Value<String?> webPageUrl = const Value.absent(),\n    Value<String?> supportUrl = const Value.absent(),\n  }) => ProfileEntriesData(\n    id: id ?? this.id,\n    type: type ?? this.type,\n    active: active ?? this.active,\n    name: name ?? this.name,\n    url: url.present ? url.value : this.url,\n    lastUpdate: lastUpdate ?? this.lastUpdate,\n    updateInterval: updateInterval.present\n        ? updateInterval.value\n        : this.updateInterval,\n    upload: upload.present ? upload.value : this.upload,\n    download: download.present ? download.value : this.download,\n    total: total.present ? total.value : this.total,\n    expire: expire.present ? expire.value : this.expire,\n    webPageUrl: webPageUrl.present ? webPageUrl.value : this.webPageUrl,\n    supportUrl: supportUrl.present ? supportUrl.value : this.supportUrl,\n  );\n  ProfileEntriesData copyWithCompanion(ProfileEntriesCompanion data) {\n    return ProfileEntriesData(\n      id: data.id.present ? data.id.value : this.id,\n      type: data.type.present ? data.type.value : this.type,\n      active: data.active.present ? data.active.value : this.active,\n      name: data.name.present ? data.name.value : this.name,\n      url: data.url.present ? data.url.value : this.url,\n      lastUpdate: data.lastUpdate.present\n          ? data.lastUpdate.value\n          : this.lastUpdate,\n      updateInterval: data.updateInterval.present\n          ? data.updateInterval.value\n          : this.updateInterval,\n      upload: data.upload.present ? data.upload.value : this.upload,\n      download: data.download.present ? data.download.value : this.download,\n      total: data.total.present ? data.total.value : this.total,\n      expire: data.expire.present ? data.expire.value : this.expire,\n      webPageUrl: data.webPageUrl.present\n          ? data.webPageUrl.value\n          : this.webPageUrl,\n      supportUrl: data.supportUrl.present\n          ? data.supportUrl.value\n          : this.supportUrl,\n    );\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('ProfileEntriesData(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('url: $url, ')\n          ..write('lastUpdate: $lastUpdate, ')\n          ..write('updateInterval: $updateInterval, ')\n          ..write('upload: $upload, ')\n          ..write('download: $download, ')\n          ..write('total: $total, ')\n          ..write('expire: $expire, ')\n          ..write('webPageUrl: $webPageUrl, ')\n          ..write('supportUrl: $supportUrl')\n          ..write(')'))\n        .toString();\n  }\n\n  @override\n  int get hashCode => Object.hash(\n    id,\n    type,\n    active,\n    name,\n    url,\n    lastUpdate,\n    updateInterval,\n    upload,\n    download,\n    total,\n    expire,\n    webPageUrl,\n    supportUrl,\n  );\n  @override\n  bool operator ==(Object other) =>\n      identical(this, other) ||\n      (other is ProfileEntriesData &&\n          other.id == this.id &&\n          other.type == this.type &&\n          other.active == this.active &&\n          other.name == this.name &&\n          other.url == this.url &&\n          other.lastUpdate == this.lastUpdate &&\n          other.updateInterval == this.updateInterval &&\n          other.upload == this.upload &&\n          other.download == this.download &&\n          other.total == this.total &&\n          other.expire == this.expire &&\n          other.webPageUrl == this.webPageUrl &&\n          other.supportUrl == this.supportUrl);\n}\n\nclass ProfileEntriesCompanion extends UpdateCompanion<ProfileEntriesData> {\n  final Value<String> id;\n  final Value<String> type;\n  final Value<bool> active;\n  final Value<String> name;\n  final Value<String?> url;\n  final Value<DateTime> lastUpdate;\n  final Value<int?> updateInterval;\n  final Value<int?> upload;\n  final Value<int?> download;\n  final Value<int?> total;\n  final Value<DateTime?> expire;\n  final Value<String?> webPageUrl;\n  final Value<String?> supportUrl;\n  final Value<int> rowid;\n  const ProfileEntriesCompanion({\n    this.id = const Value.absent(),\n    this.type = const Value.absent(),\n    this.active = const Value.absent(),\n    this.name = const Value.absent(),\n    this.url = const Value.absent(),\n    this.lastUpdate = const Value.absent(),\n    this.updateInterval = const Value.absent(),\n    this.upload = const Value.absent(),\n    this.download = const Value.absent(),\n    this.total = const Value.absent(),\n    this.expire = const Value.absent(),\n    this.webPageUrl = const Value.absent(),\n    this.supportUrl = const Value.absent(),\n    this.rowid = const Value.absent(),\n  });\n  ProfileEntriesCompanion.insert({\n    required String id,\n    required String type,\n    required bool active,\n    required String name,\n    this.url = const Value.absent(),\n    required DateTime lastUpdate,\n    this.updateInterval = const Value.absent(),\n    this.upload = const Value.absent(),\n    this.download = const Value.absent(),\n    this.total = const Value.absent(),\n    this.expire = const Value.absent(),\n    this.webPageUrl = const Value.absent(),\n    this.supportUrl = const Value.absent(),\n    this.rowid = const Value.absent(),\n  }) : id = Value(id),\n       type = Value(type),\n       active = Value(active),\n       name = Value(name),\n       lastUpdate = Value(lastUpdate);\n  static Insertable<ProfileEntriesData> custom({\n    Expression<String>? id,\n    Expression<String>? type,\n    Expression<bool>? active,\n    Expression<String>? name,\n    Expression<String>? url,\n    Expression<DateTime>? lastUpdate,\n    Expression<int>? updateInterval,\n    Expression<int>? upload,\n    Expression<int>? download,\n    Expression<int>? total,\n    Expression<DateTime>? expire,\n    Expression<String>? webPageUrl,\n    Expression<String>? supportUrl,\n    Expression<int>? rowid,\n  }) {\n    return RawValuesInsertable({\n      if (id != null) 'id': id,\n      if (type != null) 'type': type,\n      if (active != null) 'active': active,\n      if (name != null) 'name': name,\n      if (url != null) 'url': url,\n      if (lastUpdate != null) 'last_update': lastUpdate,\n      if (updateInterval != null) 'update_interval': updateInterval,\n      if (upload != null) 'upload': upload,\n      if (download != null) 'download': download,\n      if (total != null) 'total': total,\n      if (expire != null) 'expire': expire,\n      if (webPageUrl != null) 'web_page_url': webPageUrl,\n      if (supportUrl != null) 'support_url': supportUrl,\n      if (rowid != null) 'rowid': rowid,\n    });\n  }\n\n  ProfileEntriesCompanion copyWith({\n    Value<String>? id,\n    Value<String>? type,\n    Value<bool>? active,\n    Value<String>? name,\n    Value<String?>? url,\n    Value<DateTime>? lastUpdate,\n    Value<int?>? updateInterval,\n    Value<int?>? upload,\n    Value<int?>? download,\n    Value<int?>? total,\n    Value<DateTime?>? expire,\n    Value<String?>? webPageUrl,\n    Value<String?>? supportUrl,\n    Value<int>? rowid,\n  }) {\n    return ProfileEntriesCompanion(\n      id: id ?? this.id,\n      type: type ?? this.type,\n      active: active ?? this.active,\n      name: name ?? this.name,\n      url: url ?? this.url,\n      lastUpdate: lastUpdate ?? this.lastUpdate,\n      updateInterval: updateInterval ?? this.updateInterval,\n      upload: upload ?? this.upload,\n      download: download ?? this.download,\n      total: total ?? this.total,\n      expire: expire ?? this.expire,\n      webPageUrl: webPageUrl ?? this.webPageUrl,\n      supportUrl: supportUrl ?? this.supportUrl,\n      rowid: rowid ?? this.rowid,\n    );\n  }\n\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    if (id.present) {\n      map['id'] = Variable<String>(id.value);\n    }\n    if (type.present) {\n      map['type'] = Variable<String>(type.value);\n    }\n    if (active.present) {\n      map['active'] = Variable<bool>(active.value);\n    }\n    if (name.present) {\n      map['name'] = Variable<String>(name.value);\n    }\n    if (url.present) {\n      map['url'] = Variable<String>(url.value);\n    }\n    if (lastUpdate.present) {\n      map['last_update'] = Variable<DateTime>(lastUpdate.value);\n    }\n    if (updateInterval.present) {\n      map['update_interval'] = Variable<int>(updateInterval.value);\n    }\n    if (upload.present) {\n      map['upload'] = Variable<int>(upload.value);\n    }\n    if (download.present) {\n      map['download'] = Variable<int>(download.value);\n    }\n    if (total.present) {\n      map['total'] = Variable<int>(total.value);\n    }\n    if (expire.present) {\n      map['expire'] = Variable<DateTime>(expire.value);\n    }\n    if (webPageUrl.present) {\n      map['web_page_url'] = Variable<String>(webPageUrl.value);\n    }\n    if (supportUrl.present) {\n      map['support_url'] = Variable<String>(supportUrl.value);\n    }\n    if (rowid.present) {\n      map['rowid'] = Variable<int>(rowid.value);\n    }\n    return map;\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('ProfileEntriesCompanion(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('url: $url, ')\n          ..write('lastUpdate: $lastUpdate, ')\n          ..write('updateInterval: $updateInterval, ')\n          ..write('upload: $upload, ')\n          ..write('download: $download, ')\n          ..write('total: $total, ')\n          ..write('expire: $expire, ')\n          ..write('webPageUrl: $webPageUrl, ')\n          ..write('supportUrl: $supportUrl, ')\n          ..write('rowid: $rowid')\n          ..write(')'))\n        .toString();\n  }\n}\n\nclass DatabaseAtV2 extends GeneratedDatabase {\n  DatabaseAtV2(QueryExecutor e) : super(e);\n  late final ProfileEntries profileEntries = ProfileEntries(this);\n  @override\n  Iterable<TableInfo<Table, Object?>> get allTables =>\n      allSchemaEntities.whereType<TableInfo<Table, Object?>>();\n  @override\n  List<DatabaseSchemaEntity> get allSchemaEntities => [profileEntries];\n  @override\n  int get schemaVersion => 2;\n  @override\n  DriftDatabaseOptions get options =>\n      const DriftDatabaseOptions(storeDateTimeAsText: true);\n}\n"
  },
  {
    "path": "test/drift/db/generated/schema_v3.dart",
    "content": "// dart format width=80\n// GENERATED CODE, DO NOT EDIT BY HAND.\n// ignore_for_file: type=lint\nimport 'package:drift/drift.dart';\n\nclass ProfileEntries extends Table\n    with TableInfo<ProfileEntries, ProfileEntriesData> {\n  @override\n  final GeneratedDatabase attachedDatabase;\n  final String? _alias;\n  ProfileEntries(this.attachedDatabase, [this._alias]);\n  late final GeneratedColumn<String> id = GeneratedColumn<String>(\n    'id',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> type = GeneratedColumn<String>(\n    'type',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<bool> active = GeneratedColumn<bool>(\n    'active',\n    aliasedName,\n    false,\n    type: DriftSqlType.bool,\n    requiredDuringInsert: true,\n    defaultConstraints: GeneratedColumn.constraintIsAlways(\n      'CHECK (\"active\" IN (0, 1))',\n    ),\n  );\n  late final GeneratedColumn<String> name = GeneratedColumn<String>(\n    'name',\n    aliasedName,\n    false,\n    additionalChecks: GeneratedColumn.checkTextLength(minTextLength: 1),\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> url = GeneratedColumn<String>(\n    'url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> lastUpdate = GeneratedColumn<DateTime>(\n    'last_update',\n    aliasedName,\n    false,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<int> updateInterval = GeneratedColumn<int>(\n    'update_interval',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> upload = GeneratedColumn<int>(\n    'upload',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> download = GeneratedColumn<int>(\n    'download',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> total = GeneratedColumn<int>(\n    'total',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> expire = GeneratedColumn<DateTime>(\n    'expire',\n    aliasedName,\n    true,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> webPageUrl = GeneratedColumn<String>(\n    'web_page_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> supportUrl = GeneratedColumn<String>(\n    'support_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  @override\n  List<GeneratedColumn> get $columns => [\n    id,\n    type,\n    active,\n    name,\n    url,\n    lastUpdate,\n    updateInterval,\n    upload,\n    download,\n    total,\n    expire,\n    webPageUrl,\n    supportUrl,\n  ];\n  @override\n  String get aliasedName => _alias ?? actualTableName;\n  @override\n  String get actualTableName => $name;\n  static const String $name = 'profile_entries';\n  @override\n  Set<GeneratedColumn> get $primaryKey => {id};\n  @override\n  ProfileEntriesData map(Map<String, dynamic> data, {String? tablePrefix}) {\n    final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';\n    return ProfileEntriesData(\n      id: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}id'],\n      )!,\n      type: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}type'],\n      )!,\n      active: attachedDatabase.typeMapping.read(\n        DriftSqlType.bool,\n        data['${effectivePrefix}active'],\n      )!,\n      name: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}name'],\n      )!,\n      url: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}url'],\n      ),\n      lastUpdate: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}last_update'],\n      )!,\n      updateInterval: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}update_interval'],\n      ),\n      upload: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}upload'],\n      ),\n      download: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}download'],\n      ),\n      total: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}total'],\n      ),\n      expire: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}expire'],\n      ),\n      webPageUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}web_page_url'],\n      ),\n      supportUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}support_url'],\n      ),\n    );\n  }\n\n  @override\n  ProfileEntries createAlias(String alias) {\n    return ProfileEntries(attachedDatabase, alias);\n  }\n}\n\nclass ProfileEntriesData extends DataClass\n    implements Insertable<ProfileEntriesData> {\n  final String id;\n  final String type;\n  final bool active;\n  final String name;\n  final String? url;\n  final DateTime lastUpdate;\n  final int? updateInterval;\n  final int? upload;\n  final int? download;\n  final int? total;\n  final DateTime? expire;\n  final String? webPageUrl;\n  final String? supportUrl;\n  const ProfileEntriesData({\n    required this.id,\n    required this.type,\n    required this.active,\n    required this.name,\n    this.url,\n    required this.lastUpdate,\n    this.updateInterval,\n    this.upload,\n    this.download,\n    this.total,\n    this.expire,\n    this.webPageUrl,\n    this.supportUrl,\n  });\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    map['id'] = Variable<String>(id);\n    map['type'] = Variable<String>(type);\n    map['active'] = Variable<bool>(active);\n    map['name'] = Variable<String>(name);\n    if (!nullToAbsent || url != null) {\n      map['url'] = Variable<String>(url);\n    }\n    map['last_update'] = Variable<DateTime>(lastUpdate);\n    if (!nullToAbsent || updateInterval != null) {\n      map['update_interval'] = Variable<int>(updateInterval);\n    }\n    if (!nullToAbsent || upload != null) {\n      map['upload'] = Variable<int>(upload);\n    }\n    if (!nullToAbsent || download != null) {\n      map['download'] = Variable<int>(download);\n    }\n    if (!nullToAbsent || total != null) {\n      map['total'] = Variable<int>(total);\n    }\n    if (!nullToAbsent || expire != null) {\n      map['expire'] = Variable<DateTime>(expire);\n    }\n    if (!nullToAbsent || webPageUrl != null) {\n      map['web_page_url'] = Variable<String>(webPageUrl);\n    }\n    if (!nullToAbsent || supportUrl != null) {\n      map['support_url'] = Variable<String>(supportUrl);\n    }\n    return map;\n  }\n\n  ProfileEntriesCompanion toCompanion(bool nullToAbsent) {\n    return ProfileEntriesCompanion(\n      id: Value(id),\n      type: Value(type),\n      active: Value(active),\n      name: Value(name),\n      url: url == null && nullToAbsent ? const Value.absent() : Value(url),\n      lastUpdate: Value(lastUpdate),\n      updateInterval: updateInterval == null && nullToAbsent\n          ? const Value.absent()\n          : Value(updateInterval),\n      upload: upload == null && nullToAbsent\n          ? const Value.absent()\n          : Value(upload),\n      download: download == null && nullToAbsent\n          ? const Value.absent()\n          : Value(download),\n      total: total == null && nullToAbsent\n          ? const Value.absent()\n          : Value(total),\n      expire: expire == null && nullToAbsent\n          ? const Value.absent()\n          : Value(expire),\n      webPageUrl: webPageUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(webPageUrl),\n      supportUrl: supportUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(supportUrl),\n    );\n  }\n\n  factory ProfileEntriesData.fromJson(\n    Map<String, dynamic> json, {\n    ValueSerializer? serializer,\n  }) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return ProfileEntriesData(\n      id: serializer.fromJson<String>(json['id']),\n      type: serializer.fromJson<String>(json['type']),\n      active: serializer.fromJson<bool>(json['active']),\n      name: serializer.fromJson<String>(json['name']),\n      url: serializer.fromJson<String?>(json['url']),\n      lastUpdate: serializer.fromJson<DateTime>(json['lastUpdate']),\n      updateInterval: serializer.fromJson<int?>(json['updateInterval']),\n      upload: serializer.fromJson<int?>(json['upload']),\n      download: serializer.fromJson<int?>(json['download']),\n      total: serializer.fromJson<int?>(json['total']),\n      expire: serializer.fromJson<DateTime?>(json['expire']),\n      webPageUrl: serializer.fromJson<String?>(json['webPageUrl']),\n      supportUrl: serializer.fromJson<String?>(json['supportUrl']),\n    );\n  }\n  @override\n  Map<String, dynamic> toJson({ValueSerializer? serializer}) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return <String, dynamic>{\n      'id': serializer.toJson<String>(id),\n      'type': serializer.toJson<String>(type),\n      'active': serializer.toJson<bool>(active),\n      'name': serializer.toJson<String>(name),\n      'url': serializer.toJson<String?>(url),\n      'lastUpdate': serializer.toJson<DateTime>(lastUpdate),\n      'updateInterval': serializer.toJson<int?>(updateInterval),\n      'upload': serializer.toJson<int?>(upload),\n      'download': serializer.toJson<int?>(download),\n      'total': serializer.toJson<int?>(total),\n      'expire': serializer.toJson<DateTime?>(expire),\n      'webPageUrl': serializer.toJson<String?>(webPageUrl),\n      'supportUrl': serializer.toJson<String?>(supportUrl),\n    };\n  }\n\n  ProfileEntriesData copyWith({\n    String? id,\n    String? type,\n    bool? active,\n    String? name,\n    Value<String?> url = const Value.absent(),\n    DateTime? lastUpdate,\n    Value<int?> updateInterval = const Value.absent(),\n    Value<int?> upload = const Value.absent(),\n    Value<int?> download = const Value.absent(),\n    Value<int?> total = const Value.absent(),\n    Value<DateTime?> expire = const Value.absent(),\n    Value<String?> webPageUrl = const Value.absent(),\n    Value<String?> supportUrl = const Value.absent(),\n  }) => ProfileEntriesData(\n    id: id ?? this.id,\n    type: type ?? this.type,\n    active: active ?? this.active,\n    name: name ?? this.name,\n    url: url.present ? url.value : this.url,\n    lastUpdate: lastUpdate ?? this.lastUpdate,\n    updateInterval: updateInterval.present\n        ? updateInterval.value\n        : this.updateInterval,\n    upload: upload.present ? upload.value : this.upload,\n    download: download.present ? download.value : this.download,\n    total: total.present ? total.value : this.total,\n    expire: expire.present ? expire.value : this.expire,\n    webPageUrl: webPageUrl.present ? webPageUrl.value : this.webPageUrl,\n    supportUrl: supportUrl.present ? supportUrl.value : this.supportUrl,\n  );\n  ProfileEntriesData copyWithCompanion(ProfileEntriesCompanion data) {\n    return ProfileEntriesData(\n      id: data.id.present ? data.id.value : this.id,\n      type: data.type.present ? data.type.value : this.type,\n      active: data.active.present ? data.active.value : this.active,\n      name: data.name.present ? data.name.value : this.name,\n      url: data.url.present ? data.url.value : this.url,\n      lastUpdate: data.lastUpdate.present\n          ? data.lastUpdate.value\n          : this.lastUpdate,\n      updateInterval: data.updateInterval.present\n          ? data.updateInterval.value\n          : this.updateInterval,\n      upload: data.upload.present ? data.upload.value : this.upload,\n      download: data.download.present ? data.download.value : this.download,\n      total: data.total.present ? data.total.value : this.total,\n      expire: data.expire.present ? data.expire.value : this.expire,\n      webPageUrl: data.webPageUrl.present\n          ? data.webPageUrl.value\n          : this.webPageUrl,\n      supportUrl: data.supportUrl.present\n          ? data.supportUrl.value\n          : this.supportUrl,\n    );\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('ProfileEntriesData(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('url: $url, ')\n          ..write('lastUpdate: $lastUpdate, ')\n          ..write('updateInterval: $updateInterval, ')\n          ..write('upload: $upload, ')\n          ..write('download: $download, ')\n          ..write('total: $total, ')\n          ..write('expire: $expire, ')\n          ..write('webPageUrl: $webPageUrl, ')\n          ..write('supportUrl: $supportUrl')\n          ..write(')'))\n        .toString();\n  }\n\n  @override\n  int get hashCode => Object.hash(\n    id,\n    type,\n    active,\n    name,\n    url,\n    lastUpdate,\n    updateInterval,\n    upload,\n    download,\n    total,\n    expire,\n    webPageUrl,\n    supportUrl,\n  );\n  @override\n  bool operator ==(Object other) =>\n      identical(this, other) ||\n      (other is ProfileEntriesData &&\n          other.id == this.id &&\n          other.type == this.type &&\n          other.active == this.active &&\n          other.name == this.name &&\n          other.url == this.url &&\n          other.lastUpdate == this.lastUpdate &&\n          other.updateInterval == this.updateInterval &&\n          other.upload == this.upload &&\n          other.download == this.download &&\n          other.total == this.total &&\n          other.expire == this.expire &&\n          other.webPageUrl == this.webPageUrl &&\n          other.supportUrl == this.supportUrl);\n}\n\nclass ProfileEntriesCompanion extends UpdateCompanion<ProfileEntriesData> {\n  final Value<String> id;\n  final Value<String> type;\n  final Value<bool> active;\n  final Value<String> name;\n  final Value<String?> url;\n  final Value<DateTime> lastUpdate;\n  final Value<int?> updateInterval;\n  final Value<int?> upload;\n  final Value<int?> download;\n  final Value<int?> total;\n  final Value<DateTime?> expire;\n  final Value<String?> webPageUrl;\n  final Value<String?> supportUrl;\n  final Value<int> rowid;\n  const ProfileEntriesCompanion({\n    this.id = const Value.absent(),\n    this.type = const Value.absent(),\n    this.active = const Value.absent(),\n    this.name = const Value.absent(),\n    this.url = const Value.absent(),\n    this.lastUpdate = const Value.absent(),\n    this.updateInterval = const Value.absent(),\n    this.upload = const Value.absent(),\n    this.download = const Value.absent(),\n    this.total = const Value.absent(),\n    this.expire = const Value.absent(),\n    this.webPageUrl = const Value.absent(),\n    this.supportUrl = const Value.absent(),\n    this.rowid = const Value.absent(),\n  });\n  ProfileEntriesCompanion.insert({\n    required String id,\n    required String type,\n    required bool active,\n    required String name,\n    this.url = const Value.absent(),\n    required DateTime lastUpdate,\n    this.updateInterval = const Value.absent(),\n    this.upload = const Value.absent(),\n    this.download = const Value.absent(),\n    this.total = const Value.absent(),\n    this.expire = const Value.absent(),\n    this.webPageUrl = const Value.absent(),\n    this.supportUrl = const Value.absent(),\n    this.rowid = const Value.absent(),\n  }) : id = Value(id),\n       type = Value(type),\n       active = Value(active),\n       name = Value(name),\n       lastUpdate = Value(lastUpdate);\n  static Insertable<ProfileEntriesData> custom({\n    Expression<String>? id,\n    Expression<String>? type,\n    Expression<bool>? active,\n    Expression<String>? name,\n    Expression<String>? url,\n    Expression<DateTime>? lastUpdate,\n    Expression<int>? updateInterval,\n    Expression<int>? upload,\n    Expression<int>? download,\n    Expression<int>? total,\n    Expression<DateTime>? expire,\n    Expression<String>? webPageUrl,\n    Expression<String>? supportUrl,\n    Expression<int>? rowid,\n  }) {\n    return RawValuesInsertable({\n      if (id != null) 'id': id,\n      if (type != null) 'type': type,\n      if (active != null) 'active': active,\n      if (name != null) 'name': name,\n      if (url != null) 'url': url,\n      if (lastUpdate != null) 'last_update': lastUpdate,\n      if (updateInterval != null) 'update_interval': updateInterval,\n      if (upload != null) 'upload': upload,\n      if (download != null) 'download': download,\n      if (total != null) 'total': total,\n      if (expire != null) 'expire': expire,\n      if (webPageUrl != null) 'web_page_url': webPageUrl,\n      if (supportUrl != null) 'support_url': supportUrl,\n      if (rowid != null) 'rowid': rowid,\n    });\n  }\n\n  ProfileEntriesCompanion copyWith({\n    Value<String>? id,\n    Value<String>? type,\n    Value<bool>? active,\n    Value<String>? name,\n    Value<String?>? url,\n    Value<DateTime>? lastUpdate,\n    Value<int?>? updateInterval,\n    Value<int?>? upload,\n    Value<int?>? download,\n    Value<int?>? total,\n    Value<DateTime?>? expire,\n    Value<String?>? webPageUrl,\n    Value<String?>? supportUrl,\n    Value<int>? rowid,\n  }) {\n    return ProfileEntriesCompanion(\n      id: id ?? this.id,\n      type: type ?? this.type,\n      active: active ?? this.active,\n      name: name ?? this.name,\n      url: url ?? this.url,\n      lastUpdate: lastUpdate ?? this.lastUpdate,\n      updateInterval: updateInterval ?? this.updateInterval,\n      upload: upload ?? this.upload,\n      download: download ?? this.download,\n      total: total ?? this.total,\n      expire: expire ?? this.expire,\n      webPageUrl: webPageUrl ?? this.webPageUrl,\n      supportUrl: supportUrl ?? this.supportUrl,\n      rowid: rowid ?? this.rowid,\n    );\n  }\n\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    if (id.present) {\n      map['id'] = Variable<String>(id.value);\n    }\n    if (type.present) {\n      map['type'] = Variable<String>(type.value);\n    }\n    if (active.present) {\n      map['active'] = Variable<bool>(active.value);\n    }\n    if (name.present) {\n      map['name'] = Variable<String>(name.value);\n    }\n    if (url.present) {\n      map['url'] = Variable<String>(url.value);\n    }\n    if (lastUpdate.present) {\n      map['last_update'] = Variable<DateTime>(lastUpdate.value);\n    }\n    if (updateInterval.present) {\n      map['update_interval'] = Variable<int>(updateInterval.value);\n    }\n    if (upload.present) {\n      map['upload'] = Variable<int>(upload.value);\n    }\n    if (download.present) {\n      map['download'] = Variable<int>(download.value);\n    }\n    if (total.present) {\n      map['total'] = Variable<int>(total.value);\n    }\n    if (expire.present) {\n      map['expire'] = Variable<DateTime>(expire.value);\n    }\n    if (webPageUrl.present) {\n      map['web_page_url'] = Variable<String>(webPageUrl.value);\n    }\n    if (supportUrl.present) {\n      map['support_url'] = Variable<String>(supportUrl.value);\n    }\n    if (rowid.present) {\n      map['rowid'] = Variable<int>(rowid.value);\n    }\n    return map;\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('ProfileEntriesCompanion(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('url: $url, ')\n          ..write('lastUpdate: $lastUpdate, ')\n          ..write('updateInterval: $updateInterval, ')\n          ..write('upload: $upload, ')\n          ..write('download: $download, ')\n          ..write('total: $total, ')\n          ..write('expire: $expire, ')\n          ..write('webPageUrl: $webPageUrl, ')\n          ..write('supportUrl: $supportUrl, ')\n          ..write('rowid: $rowid')\n          ..write(')'))\n        .toString();\n  }\n}\n\nclass GeoAssetEntries extends Table\n    with TableInfo<GeoAssetEntries, GeoAssetEntriesData> {\n  @override\n  final GeneratedDatabase attachedDatabase;\n  final String? _alias;\n  GeoAssetEntries(this.attachedDatabase, [this._alias]);\n  late final GeneratedColumn<String> id = GeneratedColumn<String>(\n    'id',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> type = GeneratedColumn<String>(\n    'type',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<bool> active = GeneratedColumn<bool>(\n    'active',\n    aliasedName,\n    false,\n    type: DriftSqlType.bool,\n    requiredDuringInsert: true,\n    defaultConstraints: GeneratedColumn.constraintIsAlways(\n      'CHECK (\"active\" IN (0, 1))',\n    ),\n  );\n  late final GeneratedColumn<String> name = GeneratedColumn<String>(\n    'name',\n    aliasedName,\n    false,\n    additionalChecks: GeneratedColumn.checkTextLength(minTextLength: 1),\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> providerName = GeneratedColumn<String>(\n    'provider_name',\n    aliasedName,\n    false,\n    additionalChecks: GeneratedColumn.checkTextLength(minTextLength: 1),\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> version = GeneratedColumn<String>(\n    'version',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> lastCheck = GeneratedColumn<DateTime>(\n    'last_check',\n    aliasedName,\n    true,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: false,\n  );\n  @override\n  List<GeneratedColumn> get $columns => [\n    id,\n    type,\n    active,\n    name,\n    providerName,\n    version,\n    lastCheck,\n  ];\n  @override\n  String get aliasedName => _alias ?? actualTableName;\n  @override\n  String get actualTableName => $name;\n  static const String $name = 'geo_asset_entries';\n  @override\n  Set<GeneratedColumn> get $primaryKey => {id};\n  @override\n  List<Set<GeneratedColumn>> get uniqueKeys => [\n    {name, providerName},\n  ];\n  @override\n  GeoAssetEntriesData map(Map<String, dynamic> data, {String? tablePrefix}) {\n    final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';\n    return GeoAssetEntriesData(\n      id: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}id'],\n      )!,\n      type: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}type'],\n      )!,\n      active: attachedDatabase.typeMapping.read(\n        DriftSqlType.bool,\n        data['${effectivePrefix}active'],\n      )!,\n      name: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}name'],\n      )!,\n      providerName: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}provider_name'],\n      )!,\n      version: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}version'],\n      ),\n      lastCheck: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}last_check'],\n      ),\n    );\n  }\n\n  @override\n  GeoAssetEntries createAlias(String alias) {\n    return GeoAssetEntries(attachedDatabase, alias);\n  }\n}\n\nclass GeoAssetEntriesData extends DataClass\n    implements Insertable<GeoAssetEntriesData> {\n  final String id;\n  final String type;\n  final bool active;\n  final String name;\n  final String providerName;\n  final String? version;\n  final DateTime? lastCheck;\n  const GeoAssetEntriesData({\n    required this.id,\n    required this.type,\n    required this.active,\n    required this.name,\n    required this.providerName,\n    this.version,\n    this.lastCheck,\n  });\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    map['id'] = Variable<String>(id);\n    map['type'] = Variable<String>(type);\n    map['active'] = Variable<bool>(active);\n    map['name'] = Variable<String>(name);\n    map['provider_name'] = Variable<String>(providerName);\n    if (!nullToAbsent || version != null) {\n      map['version'] = Variable<String>(version);\n    }\n    if (!nullToAbsent || lastCheck != null) {\n      map['last_check'] = Variable<DateTime>(lastCheck);\n    }\n    return map;\n  }\n\n  GeoAssetEntriesCompanion toCompanion(bool nullToAbsent) {\n    return GeoAssetEntriesCompanion(\n      id: Value(id),\n      type: Value(type),\n      active: Value(active),\n      name: Value(name),\n      providerName: Value(providerName),\n      version: version == null && nullToAbsent\n          ? const Value.absent()\n          : Value(version),\n      lastCheck: lastCheck == null && nullToAbsent\n          ? const Value.absent()\n          : Value(lastCheck),\n    );\n  }\n\n  factory GeoAssetEntriesData.fromJson(\n    Map<String, dynamic> json, {\n    ValueSerializer? serializer,\n  }) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return GeoAssetEntriesData(\n      id: serializer.fromJson<String>(json['id']),\n      type: serializer.fromJson<String>(json['type']),\n      active: serializer.fromJson<bool>(json['active']),\n      name: serializer.fromJson<String>(json['name']),\n      providerName: serializer.fromJson<String>(json['providerName']),\n      version: serializer.fromJson<String?>(json['version']),\n      lastCheck: serializer.fromJson<DateTime?>(json['lastCheck']),\n    );\n  }\n  @override\n  Map<String, dynamic> toJson({ValueSerializer? serializer}) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return <String, dynamic>{\n      'id': serializer.toJson<String>(id),\n      'type': serializer.toJson<String>(type),\n      'active': serializer.toJson<bool>(active),\n      'name': serializer.toJson<String>(name),\n      'providerName': serializer.toJson<String>(providerName),\n      'version': serializer.toJson<String?>(version),\n      'lastCheck': serializer.toJson<DateTime?>(lastCheck),\n    };\n  }\n\n  GeoAssetEntriesData copyWith({\n    String? id,\n    String? type,\n    bool? active,\n    String? name,\n    String? providerName,\n    Value<String?> version = const Value.absent(),\n    Value<DateTime?> lastCheck = const Value.absent(),\n  }) => GeoAssetEntriesData(\n    id: id ?? this.id,\n    type: type ?? this.type,\n    active: active ?? this.active,\n    name: name ?? this.name,\n    providerName: providerName ?? this.providerName,\n    version: version.present ? version.value : this.version,\n    lastCheck: lastCheck.present ? lastCheck.value : this.lastCheck,\n  );\n  GeoAssetEntriesData copyWithCompanion(GeoAssetEntriesCompanion data) {\n    return GeoAssetEntriesData(\n      id: data.id.present ? data.id.value : this.id,\n      type: data.type.present ? data.type.value : this.type,\n      active: data.active.present ? data.active.value : this.active,\n      name: data.name.present ? data.name.value : this.name,\n      providerName: data.providerName.present\n          ? data.providerName.value\n          : this.providerName,\n      version: data.version.present ? data.version.value : this.version,\n      lastCheck: data.lastCheck.present ? data.lastCheck.value : this.lastCheck,\n    );\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('GeoAssetEntriesData(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('providerName: $providerName, ')\n          ..write('version: $version, ')\n          ..write('lastCheck: $lastCheck')\n          ..write(')'))\n        .toString();\n  }\n\n  @override\n  int get hashCode =>\n      Object.hash(id, type, active, name, providerName, version, lastCheck);\n  @override\n  bool operator ==(Object other) =>\n      identical(this, other) ||\n      (other is GeoAssetEntriesData &&\n          other.id == this.id &&\n          other.type == this.type &&\n          other.active == this.active &&\n          other.name == this.name &&\n          other.providerName == this.providerName &&\n          other.version == this.version &&\n          other.lastCheck == this.lastCheck);\n}\n\nclass GeoAssetEntriesCompanion extends UpdateCompanion<GeoAssetEntriesData> {\n  final Value<String> id;\n  final Value<String> type;\n  final Value<bool> active;\n  final Value<String> name;\n  final Value<String> providerName;\n  final Value<String?> version;\n  final Value<DateTime?> lastCheck;\n  final Value<int> rowid;\n  const GeoAssetEntriesCompanion({\n    this.id = const Value.absent(),\n    this.type = const Value.absent(),\n    this.active = const Value.absent(),\n    this.name = const Value.absent(),\n    this.providerName = const Value.absent(),\n    this.version = const Value.absent(),\n    this.lastCheck = const Value.absent(),\n    this.rowid = const Value.absent(),\n  });\n  GeoAssetEntriesCompanion.insert({\n    required String id,\n    required String type,\n    required bool active,\n    required String name,\n    required String providerName,\n    this.version = const Value.absent(),\n    this.lastCheck = const Value.absent(),\n    this.rowid = const Value.absent(),\n  }) : id = Value(id),\n       type = Value(type),\n       active = Value(active),\n       name = Value(name),\n       providerName = Value(providerName);\n  static Insertable<GeoAssetEntriesData> custom({\n    Expression<String>? id,\n    Expression<String>? type,\n    Expression<bool>? active,\n    Expression<String>? name,\n    Expression<String>? providerName,\n    Expression<String>? version,\n    Expression<DateTime>? lastCheck,\n    Expression<int>? rowid,\n  }) {\n    return RawValuesInsertable({\n      if (id != null) 'id': id,\n      if (type != null) 'type': type,\n      if (active != null) 'active': active,\n      if (name != null) 'name': name,\n      if (providerName != null) 'provider_name': providerName,\n      if (version != null) 'version': version,\n      if (lastCheck != null) 'last_check': lastCheck,\n      if (rowid != null) 'rowid': rowid,\n    });\n  }\n\n  GeoAssetEntriesCompanion copyWith({\n    Value<String>? id,\n    Value<String>? type,\n    Value<bool>? active,\n    Value<String>? name,\n    Value<String>? providerName,\n    Value<String?>? version,\n    Value<DateTime?>? lastCheck,\n    Value<int>? rowid,\n  }) {\n    return GeoAssetEntriesCompanion(\n      id: id ?? this.id,\n      type: type ?? this.type,\n      active: active ?? this.active,\n      name: name ?? this.name,\n      providerName: providerName ?? this.providerName,\n      version: version ?? this.version,\n      lastCheck: lastCheck ?? this.lastCheck,\n      rowid: rowid ?? this.rowid,\n    );\n  }\n\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    if (id.present) {\n      map['id'] = Variable<String>(id.value);\n    }\n    if (type.present) {\n      map['type'] = Variable<String>(type.value);\n    }\n    if (active.present) {\n      map['active'] = Variable<bool>(active.value);\n    }\n    if (name.present) {\n      map['name'] = Variable<String>(name.value);\n    }\n    if (providerName.present) {\n      map['provider_name'] = Variable<String>(providerName.value);\n    }\n    if (version.present) {\n      map['version'] = Variable<String>(version.value);\n    }\n    if (lastCheck.present) {\n      map['last_check'] = Variable<DateTime>(lastCheck.value);\n    }\n    if (rowid.present) {\n      map['rowid'] = Variable<int>(rowid.value);\n    }\n    return map;\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('GeoAssetEntriesCompanion(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('providerName: $providerName, ')\n          ..write('version: $version, ')\n          ..write('lastCheck: $lastCheck, ')\n          ..write('rowid: $rowid')\n          ..write(')'))\n        .toString();\n  }\n}\n\nclass DatabaseAtV3 extends GeneratedDatabase {\n  DatabaseAtV3(QueryExecutor e) : super(e);\n  late final ProfileEntries profileEntries = ProfileEntries(this);\n  late final GeoAssetEntries geoAssetEntries = GeoAssetEntries(this);\n  @override\n  Iterable<TableInfo<Table, Object?>> get allTables =>\n      allSchemaEntities.whereType<TableInfo<Table, Object?>>();\n  @override\n  List<DatabaseSchemaEntity> get allSchemaEntities => [\n    profileEntries,\n    geoAssetEntries,\n  ];\n  @override\n  int get schemaVersion => 3;\n  @override\n  DriftDatabaseOptions get options =>\n      const DriftDatabaseOptions(storeDateTimeAsText: true);\n}\n"
  },
  {
    "path": "test/drift/db/generated/schema_v4.dart",
    "content": "// dart format width=80\n// GENERATED CODE, DO NOT EDIT BY HAND.\n// ignore_for_file: type=lint\nimport 'package:drift/drift.dart';\n\nclass ProfileEntries extends Table\n    with TableInfo<ProfileEntries, ProfileEntriesData> {\n  @override\n  final GeneratedDatabase attachedDatabase;\n  final String? _alias;\n  ProfileEntries(this.attachedDatabase, [this._alias]);\n  late final GeneratedColumn<String> id = GeneratedColumn<String>(\n    'id',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> type = GeneratedColumn<String>(\n    'type',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<bool> active = GeneratedColumn<bool>(\n    'active',\n    aliasedName,\n    false,\n    type: DriftSqlType.bool,\n    requiredDuringInsert: true,\n    defaultConstraints: GeneratedColumn.constraintIsAlways(\n      'CHECK (\"active\" IN (0, 1))',\n    ),\n  );\n  late final GeneratedColumn<String> name = GeneratedColumn<String>(\n    'name',\n    aliasedName,\n    false,\n    additionalChecks: GeneratedColumn.checkTextLength(minTextLength: 1),\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> url = GeneratedColumn<String>(\n    'url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> lastUpdate = GeneratedColumn<DateTime>(\n    'last_update',\n    aliasedName,\n    false,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<int> updateInterval = GeneratedColumn<int>(\n    'update_interval',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> upload = GeneratedColumn<int>(\n    'upload',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> download = GeneratedColumn<int>(\n    'download',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> total = GeneratedColumn<int>(\n    'total',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> expire = GeneratedColumn<DateTime>(\n    'expire',\n    aliasedName,\n    true,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> webPageUrl = GeneratedColumn<String>(\n    'web_page_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> supportUrl = GeneratedColumn<String>(\n    'support_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> testUrl = GeneratedColumn<String>(\n    'test_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  @override\n  List<GeneratedColumn> get $columns => [\n    id,\n    type,\n    active,\n    name,\n    url,\n    lastUpdate,\n    updateInterval,\n    upload,\n    download,\n    total,\n    expire,\n    webPageUrl,\n    supportUrl,\n    testUrl,\n  ];\n  @override\n  String get aliasedName => _alias ?? actualTableName;\n  @override\n  String get actualTableName => $name;\n  static const String $name = 'profile_entries';\n  @override\n  Set<GeneratedColumn> get $primaryKey => {id};\n  @override\n  ProfileEntriesData map(Map<String, dynamic> data, {String? tablePrefix}) {\n    final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';\n    return ProfileEntriesData(\n      id: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}id'],\n      )!,\n      type: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}type'],\n      )!,\n      active: attachedDatabase.typeMapping.read(\n        DriftSqlType.bool,\n        data['${effectivePrefix}active'],\n      )!,\n      name: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}name'],\n      )!,\n      url: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}url'],\n      ),\n      lastUpdate: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}last_update'],\n      )!,\n      updateInterval: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}update_interval'],\n      ),\n      upload: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}upload'],\n      ),\n      download: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}download'],\n      ),\n      total: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}total'],\n      ),\n      expire: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}expire'],\n      ),\n      webPageUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}web_page_url'],\n      ),\n      supportUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}support_url'],\n      ),\n      testUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}test_url'],\n      ),\n    );\n  }\n\n  @override\n  ProfileEntries createAlias(String alias) {\n    return ProfileEntries(attachedDatabase, alias);\n  }\n}\n\nclass ProfileEntriesData extends DataClass\n    implements Insertable<ProfileEntriesData> {\n  final String id;\n  final String type;\n  final bool active;\n  final String name;\n  final String? url;\n  final DateTime lastUpdate;\n  final int? updateInterval;\n  final int? upload;\n  final int? download;\n  final int? total;\n  final DateTime? expire;\n  final String? webPageUrl;\n  final String? supportUrl;\n  final String? testUrl;\n  const ProfileEntriesData({\n    required this.id,\n    required this.type,\n    required this.active,\n    required this.name,\n    this.url,\n    required this.lastUpdate,\n    this.updateInterval,\n    this.upload,\n    this.download,\n    this.total,\n    this.expire,\n    this.webPageUrl,\n    this.supportUrl,\n    this.testUrl,\n  });\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    map['id'] = Variable<String>(id);\n    map['type'] = Variable<String>(type);\n    map['active'] = Variable<bool>(active);\n    map['name'] = Variable<String>(name);\n    if (!nullToAbsent || url != null) {\n      map['url'] = Variable<String>(url);\n    }\n    map['last_update'] = Variable<DateTime>(lastUpdate);\n    if (!nullToAbsent || updateInterval != null) {\n      map['update_interval'] = Variable<int>(updateInterval);\n    }\n    if (!nullToAbsent || upload != null) {\n      map['upload'] = Variable<int>(upload);\n    }\n    if (!nullToAbsent || download != null) {\n      map['download'] = Variable<int>(download);\n    }\n    if (!nullToAbsent || total != null) {\n      map['total'] = Variable<int>(total);\n    }\n    if (!nullToAbsent || expire != null) {\n      map['expire'] = Variable<DateTime>(expire);\n    }\n    if (!nullToAbsent || webPageUrl != null) {\n      map['web_page_url'] = Variable<String>(webPageUrl);\n    }\n    if (!nullToAbsent || supportUrl != null) {\n      map['support_url'] = Variable<String>(supportUrl);\n    }\n    if (!nullToAbsent || testUrl != null) {\n      map['test_url'] = Variable<String>(testUrl);\n    }\n    return map;\n  }\n\n  ProfileEntriesCompanion toCompanion(bool nullToAbsent) {\n    return ProfileEntriesCompanion(\n      id: Value(id),\n      type: Value(type),\n      active: Value(active),\n      name: Value(name),\n      url: url == null && nullToAbsent ? const Value.absent() : Value(url),\n      lastUpdate: Value(lastUpdate),\n      updateInterval: updateInterval == null && nullToAbsent\n          ? const Value.absent()\n          : Value(updateInterval),\n      upload: upload == null && nullToAbsent\n          ? const Value.absent()\n          : Value(upload),\n      download: download == null && nullToAbsent\n          ? const Value.absent()\n          : Value(download),\n      total: total == null && nullToAbsent\n          ? const Value.absent()\n          : Value(total),\n      expire: expire == null && nullToAbsent\n          ? const Value.absent()\n          : Value(expire),\n      webPageUrl: webPageUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(webPageUrl),\n      supportUrl: supportUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(supportUrl),\n      testUrl: testUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(testUrl),\n    );\n  }\n\n  factory ProfileEntriesData.fromJson(\n    Map<String, dynamic> json, {\n    ValueSerializer? serializer,\n  }) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return ProfileEntriesData(\n      id: serializer.fromJson<String>(json['id']),\n      type: serializer.fromJson<String>(json['type']),\n      active: serializer.fromJson<bool>(json['active']),\n      name: serializer.fromJson<String>(json['name']),\n      url: serializer.fromJson<String?>(json['url']),\n      lastUpdate: serializer.fromJson<DateTime>(json['lastUpdate']),\n      updateInterval: serializer.fromJson<int?>(json['updateInterval']),\n      upload: serializer.fromJson<int?>(json['upload']),\n      download: serializer.fromJson<int?>(json['download']),\n      total: serializer.fromJson<int?>(json['total']),\n      expire: serializer.fromJson<DateTime?>(json['expire']),\n      webPageUrl: serializer.fromJson<String?>(json['webPageUrl']),\n      supportUrl: serializer.fromJson<String?>(json['supportUrl']),\n      testUrl: serializer.fromJson<String?>(json['testUrl']),\n    );\n  }\n  @override\n  Map<String, dynamic> toJson({ValueSerializer? serializer}) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return <String, dynamic>{\n      'id': serializer.toJson<String>(id),\n      'type': serializer.toJson<String>(type),\n      'active': serializer.toJson<bool>(active),\n      'name': serializer.toJson<String>(name),\n      'url': serializer.toJson<String?>(url),\n      'lastUpdate': serializer.toJson<DateTime>(lastUpdate),\n      'updateInterval': serializer.toJson<int?>(updateInterval),\n      'upload': serializer.toJson<int?>(upload),\n      'download': serializer.toJson<int?>(download),\n      'total': serializer.toJson<int?>(total),\n      'expire': serializer.toJson<DateTime?>(expire),\n      'webPageUrl': serializer.toJson<String?>(webPageUrl),\n      'supportUrl': serializer.toJson<String?>(supportUrl),\n      'testUrl': serializer.toJson<String?>(testUrl),\n    };\n  }\n\n  ProfileEntriesData copyWith({\n    String? id,\n    String? type,\n    bool? active,\n    String? name,\n    Value<String?> url = const Value.absent(),\n    DateTime? lastUpdate,\n    Value<int?> updateInterval = const Value.absent(),\n    Value<int?> upload = const Value.absent(),\n    Value<int?> download = const Value.absent(),\n    Value<int?> total = const Value.absent(),\n    Value<DateTime?> expire = const Value.absent(),\n    Value<String?> webPageUrl = const Value.absent(),\n    Value<String?> supportUrl = const Value.absent(),\n    Value<String?> testUrl = const Value.absent(),\n  }) => ProfileEntriesData(\n    id: id ?? this.id,\n    type: type ?? this.type,\n    active: active ?? this.active,\n    name: name ?? this.name,\n    url: url.present ? url.value : this.url,\n    lastUpdate: lastUpdate ?? this.lastUpdate,\n    updateInterval: updateInterval.present\n        ? updateInterval.value\n        : this.updateInterval,\n    upload: upload.present ? upload.value : this.upload,\n    download: download.present ? download.value : this.download,\n    total: total.present ? total.value : this.total,\n    expire: expire.present ? expire.value : this.expire,\n    webPageUrl: webPageUrl.present ? webPageUrl.value : this.webPageUrl,\n    supportUrl: supportUrl.present ? supportUrl.value : this.supportUrl,\n    testUrl: testUrl.present ? testUrl.value : this.testUrl,\n  );\n  ProfileEntriesData copyWithCompanion(ProfileEntriesCompanion data) {\n    return ProfileEntriesData(\n      id: data.id.present ? data.id.value : this.id,\n      type: data.type.present ? data.type.value : this.type,\n      active: data.active.present ? data.active.value : this.active,\n      name: data.name.present ? data.name.value : this.name,\n      url: data.url.present ? data.url.value : this.url,\n      lastUpdate: data.lastUpdate.present\n          ? data.lastUpdate.value\n          : this.lastUpdate,\n      updateInterval: data.updateInterval.present\n          ? data.updateInterval.value\n          : this.updateInterval,\n      upload: data.upload.present ? data.upload.value : this.upload,\n      download: data.download.present ? data.download.value : this.download,\n      total: data.total.present ? data.total.value : this.total,\n      expire: data.expire.present ? data.expire.value : this.expire,\n      webPageUrl: data.webPageUrl.present\n          ? data.webPageUrl.value\n          : this.webPageUrl,\n      supportUrl: data.supportUrl.present\n          ? data.supportUrl.value\n          : this.supportUrl,\n      testUrl: data.testUrl.present ? data.testUrl.value : this.testUrl,\n    );\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('ProfileEntriesData(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('url: $url, ')\n          ..write('lastUpdate: $lastUpdate, ')\n          ..write('updateInterval: $updateInterval, ')\n          ..write('upload: $upload, ')\n          ..write('download: $download, ')\n          ..write('total: $total, ')\n          ..write('expire: $expire, ')\n          ..write('webPageUrl: $webPageUrl, ')\n          ..write('supportUrl: $supportUrl, ')\n          ..write('testUrl: $testUrl')\n          ..write(')'))\n        .toString();\n  }\n\n  @override\n  int get hashCode => Object.hash(\n    id,\n    type,\n    active,\n    name,\n    url,\n    lastUpdate,\n    updateInterval,\n    upload,\n    download,\n    total,\n    expire,\n    webPageUrl,\n    supportUrl,\n    testUrl,\n  );\n  @override\n  bool operator ==(Object other) =>\n      identical(this, other) ||\n      (other is ProfileEntriesData &&\n          other.id == this.id &&\n          other.type == this.type &&\n          other.active == this.active &&\n          other.name == this.name &&\n          other.url == this.url &&\n          other.lastUpdate == this.lastUpdate &&\n          other.updateInterval == this.updateInterval &&\n          other.upload == this.upload &&\n          other.download == this.download &&\n          other.total == this.total &&\n          other.expire == this.expire &&\n          other.webPageUrl == this.webPageUrl &&\n          other.supportUrl == this.supportUrl &&\n          other.testUrl == this.testUrl);\n}\n\nclass ProfileEntriesCompanion extends UpdateCompanion<ProfileEntriesData> {\n  final Value<String> id;\n  final Value<String> type;\n  final Value<bool> active;\n  final Value<String> name;\n  final Value<String?> url;\n  final Value<DateTime> lastUpdate;\n  final Value<int?> updateInterval;\n  final Value<int?> upload;\n  final Value<int?> download;\n  final Value<int?> total;\n  final Value<DateTime?> expire;\n  final Value<String?> webPageUrl;\n  final Value<String?> supportUrl;\n  final Value<String?> testUrl;\n  final Value<int> rowid;\n  const ProfileEntriesCompanion({\n    this.id = const Value.absent(),\n    this.type = const Value.absent(),\n    this.active = const Value.absent(),\n    this.name = const Value.absent(),\n    this.url = const Value.absent(),\n    this.lastUpdate = const Value.absent(),\n    this.updateInterval = const Value.absent(),\n    this.upload = const Value.absent(),\n    this.download = const Value.absent(),\n    this.total = const Value.absent(),\n    this.expire = const Value.absent(),\n    this.webPageUrl = const Value.absent(),\n    this.supportUrl = const Value.absent(),\n    this.testUrl = const Value.absent(),\n    this.rowid = const Value.absent(),\n  });\n  ProfileEntriesCompanion.insert({\n    required String id,\n    required String type,\n    required bool active,\n    required String name,\n    this.url = const Value.absent(),\n    required DateTime lastUpdate,\n    this.updateInterval = const Value.absent(),\n    this.upload = const Value.absent(),\n    this.download = const Value.absent(),\n    this.total = const Value.absent(),\n    this.expire = const Value.absent(),\n    this.webPageUrl = const Value.absent(),\n    this.supportUrl = const Value.absent(),\n    this.testUrl = const Value.absent(),\n    this.rowid = const Value.absent(),\n  }) : id = Value(id),\n       type = Value(type),\n       active = Value(active),\n       name = Value(name),\n       lastUpdate = Value(lastUpdate);\n  static Insertable<ProfileEntriesData> custom({\n    Expression<String>? id,\n    Expression<String>? type,\n    Expression<bool>? active,\n    Expression<String>? name,\n    Expression<String>? url,\n    Expression<DateTime>? lastUpdate,\n    Expression<int>? updateInterval,\n    Expression<int>? upload,\n    Expression<int>? download,\n    Expression<int>? total,\n    Expression<DateTime>? expire,\n    Expression<String>? webPageUrl,\n    Expression<String>? supportUrl,\n    Expression<String>? testUrl,\n    Expression<int>? rowid,\n  }) {\n    return RawValuesInsertable({\n      if (id != null) 'id': id,\n      if (type != null) 'type': type,\n      if (active != null) 'active': active,\n      if (name != null) 'name': name,\n      if (url != null) 'url': url,\n      if (lastUpdate != null) 'last_update': lastUpdate,\n      if (updateInterval != null) 'update_interval': updateInterval,\n      if (upload != null) 'upload': upload,\n      if (download != null) 'download': download,\n      if (total != null) 'total': total,\n      if (expire != null) 'expire': expire,\n      if (webPageUrl != null) 'web_page_url': webPageUrl,\n      if (supportUrl != null) 'support_url': supportUrl,\n      if (testUrl != null) 'test_url': testUrl,\n      if (rowid != null) 'rowid': rowid,\n    });\n  }\n\n  ProfileEntriesCompanion copyWith({\n    Value<String>? id,\n    Value<String>? type,\n    Value<bool>? active,\n    Value<String>? name,\n    Value<String?>? url,\n    Value<DateTime>? lastUpdate,\n    Value<int?>? updateInterval,\n    Value<int?>? upload,\n    Value<int?>? download,\n    Value<int?>? total,\n    Value<DateTime?>? expire,\n    Value<String?>? webPageUrl,\n    Value<String?>? supportUrl,\n    Value<String?>? testUrl,\n    Value<int>? rowid,\n  }) {\n    return ProfileEntriesCompanion(\n      id: id ?? this.id,\n      type: type ?? this.type,\n      active: active ?? this.active,\n      name: name ?? this.name,\n      url: url ?? this.url,\n      lastUpdate: lastUpdate ?? this.lastUpdate,\n      updateInterval: updateInterval ?? this.updateInterval,\n      upload: upload ?? this.upload,\n      download: download ?? this.download,\n      total: total ?? this.total,\n      expire: expire ?? this.expire,\n      webPageUrl: webPageUrl ?? this.webPageUrl,\n      supportUrl: supportUrl ?? this.supportUrl,\n      testUrl: testUrl ?? this.testUrl,\n      rowid: rowid ?? this.rowid,\n    );\n  }\n\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    if (id.present) {\n      map['id'] = Variable<String>(id.value);\n    }\n    if (type.present) {\n      map['type'] = Variable<String>(type.value);\n    }\n    if (active.present) {\n      map['active'] = Variable<bool>(active.value);\n    }\n    if (name.present) {\n      map['name'] = Variable<String>(name.value);\n    }\n    if (url.present) {\n      map['url'] = Variable<String>(url.value);\n    }\n    if (lastUpdate.present) {\n      map['last_update'] = Variable<DateTime>(lastUpdate.value);\n    }\n    if (updateInterval.present) {\n      map['update_interval'] = Variable<int>(updateInterval.value);\n    }\n    if (upload.present) {\n      map['upload'] = Variable<int>(upload.value);\n    }\n    if (download.present) {\n      map['download'] = Variable<int>(download.value);\n    }\n    if (total.present) {\n      map['total'] = Variable<int>(total.value);\n    }\n    if (expire.present) {\n      map['expire'] = Variable<DateTime>(expire.value);\n    }\n    if (webPageUrl.present) {\n      map['web_page_url'] = Variable<String>(webPageUrl.value);\n    }\n    if (supportUrl.present) {\n      map['support_url'] = Variable<String>(supportUrl.value);\n    }\n    if (testUrl.present) {\n      map['test_url'] = Variable<String>(testUrl.value);\n    }\n    if (rowid.present) {\n      map['rowid'] = Variable<int>(rowid.value);\n    }\n    return map;\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('ProfileEntriesCompanion(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('url: $url, ')\n          ..write('lastUpdate: $lastUpdate, ')\n          ..write('updateInterval: $updateInterval, ')\n          ..write('upload: $upload, ')\n          ..write('download: $download, ')\n          ..write('total: $total, ')\n          ..write('expire: $expire, ')\n          ..write('webPageUrl: $webPageUrl, ')\n          ..write('supportUrl: $supportUrl, ')\n          ..write('testUrl: $testUrl, ')\n          ..write('rowid: $rowid')\n          ..write(')'))\n        .toString();\n  }\n}\n\nclass GeoAssetEntries extends Table\n    with TableInfo<GeoAssetEntries, GeoAssetEntriesData> {\n  @override\n  final GeneratedDatabase attachedDatabase;\n  final String? _alias;\n  GeoAssetEntries(this.attachedDatabase, [this._alias]);\n  late final GeneratedColumn<String> id = GeneratedColumn<String>(\n    'id',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> type = GeneratedColumn<String>(\n    'type',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<bool> active = GeneratedColumn<bool>(\n    'active',\n    aliasedName,\n    false,\n    type: DriftSqlType.bool,\n    requiredDuringInsert: true,\n    defaultConstraints: GeneratedColumn.constraintIsAlways(\n      'CHECK (\"active\" IN (0, 1))',\n    ),\n  );\n  late final GeneratedColumn<String> name = GeneratedColumn<String>(\n    'name',\n    aliasedName,\n    false,\n    additionalChecks: GeneratedColumn.checkTextLength(minTextLength: 1),\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> providerName = GeneratedColumn<String>(\n    'provider_name',\n    aliasedName,\n    false,\n    additionalChecks: GeneratedColumn.checkTextLength(minTextLength: 1),\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> version = GeneratedColumn<String>(\n    'version',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> lastCheck = GeneratedColumn<DateTime>(\n    'last_check',\n    aliasedName,\n    true,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: false,\n  );\n  @override\n  List<GeneratedColumn> get $columns => [\n    id,\n    type,\n    active,\n    name,\n    providerName,\n    version,\n    lastCheck,\n  ];\n  @override\n  String get aliasedName => _alias ?? actualTableName;\n  @override\n  String get actualTableName => $name;\n  static const String $name = 'geo_asset_entries';\n  @override\n  Set<GeneratedColumn> get $primaryKey => {id};\n  @override\n  List<Set<GeneratedColumn>> get uniqueKeys => [\n    {name, providerName},\n  ];\n  @override\n  GeoAssetEntriesData map(Map<String, dynamic> data, {String? tablePrefix}) {\n    final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';\n    return GeoAssetEntriesData(\n      id: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}id'],\n      )!,\n      type: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}type'],\n      )!,\n      active: attachedDatabase.typeMapping.read(\n        DriftSqlType.bool,\n        data['${effectivePrefix}active'],\n      )!,\n      name: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}name'],\n      )!,\n      providerName: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}provider_name'],\n      )!,\n      version: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}version'],\n      ),\n      lastCheck: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}last_check'],\n      ),\n    );\n  }\n\n  @override\n  GeoAssetEntries createAlias(String alias) {\n    return GeoAssetEntries(attachedDatabase, alias);\n  }\n}\n\nclass GeoAssetEntriesData extends DataClass\n    implements Insertable<GeoAssetEntriesData> {\n  final String id;\n  final String type;\n  final bool active;\n  final String name;\n  final String providerName;\n  final String? version;\n  final DateTime? lastCheck;\n  const GeoAssetEntriesData({\n    required this.id,\n    required this.type,\n    required this.active,\n    required this.name,\n    required this.providerName,\n    this.version,\n    this.lastCheck,\n  });\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    map['id'] = Variable<String>(id);\n    map['type'] = Variable<String>(type);\n    map['active'] = Variable<bool>(active);\n    map['name'] = Variable<String>(name);\n    map['provider_name'] = Variable<String>(providerName);\n    if (!nullToAbsent || version != null) {\n      map['version'] = Variable<String>(version);\n    }\n    if (!nullToAbsent || lastCheck != null) {\n      map['last_check'] = Variable<DateTime>(lastCheck);\n    }\n    return map;\n  }\n\n  GeoAssetEntriesCompanion toCompanion(bool nullToAbsent) {\n    return GeoAssetEntriesCompanion(\n      id: Value(id),\n      type: Value(type),\n      active: Value(active),\n      name: Value(name),\n      providerName: Value(providerName),\n      version: version == null && nullToAbsent\n          ? const Value.absent()\n          : Value(version),\n      lastCheck: lastCheck == null && nullToAbsent\n          ? const Value.absent()\n          : Value(lastCheck),\n    );\n  }\n\n  factory GeoAssetEntriesData.fromJson(\n    Map<String, dynamic> json, {\n    ValueSerializer? serializer,\n  }) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return GeoAssetEntriesData(\n      id: serializer.fromJson<String>(json['id']),\n      type: serializer.fromJson<String>(json['type']),\n      active: serializer.fromJson<bool>(json['active']),\n      name: serializer.fromJson<String>(json['name']),\n      providerName: serializer.fromJson<String>(json['providerName']),\n      version: serializer.fromJson<String?>(json['version']),\n      lastCheck: serializer.fromJson<DateTime?>(json['lastCheck']),\n    );\n  }\n  @override\n  Map<String, dynamic> toJson({ValueSerializer? serializer}) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return <String, dynamic>{\n      'id': serializer.toJson<String>(id),\n      'type': serializer.toJson<String>(type),\n      'active': serializer.toJson<bool>(active),\n      'name': serializer.toJson<String>(name),\n      'providerName': serializer.toJson<String>(providerName),\n      'version': serializer.toJson<String?>(version),\n      'lastCheck': serializer.toJson<DateTime?>(lastCheck),\n    };\n  }\n\n  GeoAssetEntriesData copyWith({\n    String? id,\n    String? type,\n    bool? active,\n    String? name,\n    String? providerName,\n    Value<String?> version = const Value.absent(),\n    Value<DateTime?> lastCheck = const Value.absent(),\n  }) => GeoAssetEntriesData(\n    id: id ?? this.id,\n    type: type ?? this.type,\n    active: active ?? this.active,\n    name: name ?? this.name,\n    providerName: providerName ?? this.providerName,\n    version: version.present ? version.value : this.version,\n    lastCheck: lastCheck.present ? lastCheck.value : this.lastCheck,\n  );\n  GeoAssetEntriesData copyWithCompanion(GeoAssetEntriesCompanion data) {\n    return GeoAssetEntriesData(\n      id: data.id.present ? data.id.value : this.id,\n      type: data.type.present ? data.type.value : this.type,\n      active: data.active.present ? data.active.value : this.active,\n      name: data.name.present ? data.name.value : this.name,\n      providerName: data.providerName.present\n          ? data.providerName.value\n          : this.providerName,\n      version: data.version.present ? data.version.value : this.version,\n      lastCheck: data.lastCheck.present ? data.lastCheck.value : this.lastCheck,\n    );\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('GeoAssetEntriesData(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('providerName: $providerName, ')\n          ..write('version: $version, ')\n          ..write('lastCheck: $lastCheck')\n          ..write(')'))\n        .toString();\n  }\n\n  @override\n  int get hashCode =>\n      Object.hash(id, type, active, name, providerName, version, lastCheck);\n  @override\n  bool operator ==(Object other) =>\n      identical(this, other) ||\n      (other is GeoAssetEntriesData &&\n          other.id == this.id &&\n          other.type == this.type &&\n          other.active == this.active &&\n          other.name == this.name &&\n          other.providerName == this.providerName &&\n          other.version == this.version &&\n          other.lastCheck == this.lastCheck);\n}\n\nclass GeoAssetEntriesCompanion extends UpdateCompanion<GeoAssetEntriesData> {\n  final Value<String> id;\n  final Value<String> type;\n  final Value<bool> active;\n  final Value<String> name;\n  final Value<String> providerName;\n  final Value<String?> version;\n  final Value<DateTime?> lastCheck;\n  final Value<int> rowid;\n  const GeoAssetEntriesCompanion({\n    this.id = const Value.absent(),\n    this.type = const Value.absent(),\n    this.active = const Value.absent(),\n    this.name = const Value.absent(),\n    this.providerName = const Value.absent(),\n    this.version = const Value.absent(),\n    this.lastCheck = const Value.absent(),\n    this.rowid = const Value.absent(),\n  });\n  GeoAssetEntriesCompanion.insert({\n    required String id,\n    required String type,\n    required bool active,\n    required String name,\n    required String providerName,\n    this.version = const Value.absent(),\n    this.lastCheck = const Value.absent(),\n    this.rowid = const Value.absent(),\n  }) : id = Value(id),\n       type = Value(type),\n       active = Value(active),\n       name = Value(name),\n       providerName = Value(providerName);\n  static Insertable<GeoAssetEntriesData> custom({\n    Expression<String>? id,\n    Expression<String>? type,\n    Expression<bool>? active,\n    Expression<String>? name,\n    Expression<String>? providerName,\n    Expression<String>? version,\n    Expression<DateTime>? lastCheck,\n    Expression<int>? rowid,\n  }) {\n    return RawValuesInsertable({\n      if (id != null) 'id': id,\n      if (type != null) 'type': type,\n      if (active != null) 'active': active,\n      if (name != null) 'name': name,\n      if (providerName != null) 'provider_name': providerName,\n      if (version != null) 'version': version,\n      if (lastCheck != null) 'last_check': lastCheck,\n      if (rowid != null) 'rowid': rowid,\n    });\n  }\n\n  GeoAssetEntriesCompanion copyWith({\n    Value<String>? id,\n    Value<String>? type,\n    Value<bool>? active,\n    Value<String>? name,\n    Value<String>? providerName,\n    Value<String?>? version,\n    Value<DateTime?>? lastCheck,\n    Value<int>? rowid,\n  }) {\n    return GeoAssetEntriesCompanion(\n      id: id ?? this.id,\n      type: type ?? this.type,\n      active: active ?? this.active,\n      name: name ?? this.name,\n      providerName: providerName ?? this.providerName,\n      version: version ?? this.version,\n      lastCheck: lastCheck ?? this.lastCheck,\n      rowid: rowid ?? this.rowid,\n    );\n  }\n\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    if (id.present) {\n      map['id'] = Variable<String>(id.value);\n    }\n    if (type.present) {\n      map['type'] = Variable<String>(type.value);\n    }\n    if (active.present) {\n      map['active'] = Variable<bool>(active.value);\n    }\n    if (name.present) {\n      map['name'] = Variable<String>(name.value);\n    }\n    if (providerName.present) {\n      map['provider_name'] = Variable<String>(providerName.value);\n    }\n    if (version.present) {\n      map['version'] = Variable<String>(version.value);\n    }\n    if (lastCheck.present) {\n      map['last_check'] = Variable<DateTime>(lastCheck.value);\n    }\n    if (rowid.present) {\n      map['rowid'] = Variable<int>(rowid.value);\n    }\n    return map;\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('GeoAssetEntriesCompanion(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('providerName: $providerName, ')\n          ..write('version: $version, ')\n          ..write('lastCheck: $lastCheck, ')\n          ..write('rowid: $rowid')\n          ..write(')'))\n        .toString();\n  }\n}\n\nclass DatabaseAtV4 extends GeneratedDatabase {\n  DatabaseAtV4(QueryExecutor e) : super(e);\n  late final ProfileEntries profileEntries = ProfileEntries(this);\n  late final GeoAssetEntries geoAssetEntries = GeoAssetEntries(this);\n  @override\n  Iterable<TableInfo<Table, Object?>> get allTables =>\n      allSchemaEntities.whereType<TableInfo<Table, Object?>>();\n  @override\n  List<DatabaseSchemaEntity> get allSchemaEntities => [\n    profileEntries,\n    geoAssetEntries,\n  ];\n  @override\n  int get schemaVersion => 4;\n  @override\n  DriftDatabaseOptions get options =>\n      const DriftDatabaseOptions(storeDateTimeAsText: true);\n}\n"
  },
  {
    "path": "test/drift/db/generated/schema_v5.dart",
    "content": "// dart format width=80\n// GENERATED CODE, DO NOT EDIT BY HAND.\n// ignore_for_file: type=lint\nimport 'package:drift/drift.dart';\n\nclass ProfileEntries extends Table\n    with TableInfo<ProfileEntries, ProfileEntriesData> {\n  @override\n  final GeneratedDatabase attachedDatabase;\n  final String? _alias;\n  ProfileEntries(this.attachedDatabase, [this._alias]);\n  late final GeneratedColumn<String> id = GeneratedColumn<String>(\n    'id',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> type = GeneratedColumn<String>(\n    'type',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<bool> active = GeneratedColumn<bool>(\n    'active',\n    aliasedName,\n    false,\n    type: DriftSqlType.bool,\n    requiredDuringInsert: true,\n    defaultConstraints: GeneratedColumn.constraintIsAlways(\n      'CHECK (\"active\" IN (0, 1))',\n    ),\n  );\n  late final GeneratedColumn<String> name = GeneratedColumn<String>(\n    'name',\n    aliasedName,\n    false,\n    additionalChecks: GeneratedColumn.checkTextLength(minTextLength: 1),\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> url = GeneratedColumn<String>(\n    'url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> lastUpdate = GeneratedColumn<DateTime>(\n    'last_update',\n    aliasedName,\n    false,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<int> updateInterval = GeneratedColumn<int>(\n    'update_interval',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> upload = GeneratedColumn<int>(\n    'upload',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> download = GeneratedColumn<int>(\n    'download',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<int> total = GeneratedColumn<int>(\n    'total',\n    aliasedName,\n    true,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<DateTime> expire = GeneratedColumn<DateTime>(\n    'expire',\n    aliasedName,\n    true,\n    type: DriftSqlType.dateTime,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> webPageUrl = GeneratedColumn<String>(\n    'web_page_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> supportUrl = GeneratedColumn<String>(\n    'support_url',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> populatedHeaders = GeneratedColumn<String>(\n    'populated_headers',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> profileOverride = GeneratedColumn<String>(\n    'profile_override',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  late final GeneratedColumn<String> userOverride = GeneratedColumn<String>(\n    'user_override',\n    aliasedName,\n    true,\n    type: DriftSqlType.string,\n    requiredDuringInsert: false,\n  );\n  @override\n  List<GeneratedColumn> get $columns => [\n    id,\n    type,\n    active,\n    name,\n    url,\n    lastUpdate,\n    updateInterval,\n    upload,\n    download,\n    total,\n    expire,\n    webPageUrl,\n    supportUrl,\n    populatedHeaders,\n    profileOverride,\n    userOverride,\n  ];\n  @override\n  String get aliasedName => _alias ?? actualTableName;\n  @override\n  String get actualTableName => $name;\n  static const String $name = 'profile_entries';\n  @override\n  Set<GeneratedColumn> get $primaryKey => {id};\n  @override\n  ProfileEntriesData map(Map<String, dynamic> data, {String? tablePrefix}) {\n    final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';\n    return ProfileEntriesData(\n      id: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}id'],\n      )!,\n      type: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}type'],\n      )!,\n      active: attachedDatabase.typeMapping.read(\n        DriftSqlType.bool,\n        data['${effectivePrefix}active'],\n      )!,\n      name: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}name'],\n      )!,\n      url: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}url'],\n      ),\n      lastUpdate: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}last_update'],\n      )!,\n      updateInterval: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}update_interval'],\n      ),\n      upload: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}upload'],\n      ),\n      download: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}download'],\n      ),\n      total: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}total'],\n      ),\n      expire: attachedDatabase.typeMapping.read(\n        DriftSqlType.dateTime,\n        data['${effectivePrefix}expire'],\n      ),\n      webPageUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}web_page_url'],\n      ),\n      supportUrl: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}support_url'],\n      ),\n      populatedHeaders: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}populated_headers'],\n      ),\n      profileOverride: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}profile_override'],\n      ),\n      userOverride: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}user_override'],\n      ),\n    );\n  }\n\n  @override\n  ProfileEntries createAlias(String alias) {\n    return ProfileEntries(attachedDatabase, alias);\n  }\n}\n\nclass ProfileEntriesData extends DataClass\n    implements Insertable<ProfileEntriesData> {\n  final String id;\n  final String type;\n  final bool active;\n  final String name;\n  final String? url;\n  final DateTime lastUpdate;\n  final int? updateInterval;\n  final int? upload;\n  final int? download;\n  final int? total;\n  final DateTime? expire;\n  final String? webPageUrl;\n  final String? supportUrl;\n  final String? populatedHeaders;\n  final String? profileOverride;\n  final String? userOverride;\n  const ProfileEntriesData({\n    required this.id,\n    required this.type,\n    required this.active,\n    required this.name,\n    this.url,\n    required this.lastUpdate,\n    this.updateInterval,\n    this.upload,\n    this.download,\n    this.total,\n    this.expire,\n    this.webPageUrl,\n    this.supportUrl,\n    this.populatedHeaders,\n    this.profileOverride,\n    this.userOverride,\n  });\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    map['id'] = Variable<String>(id);\n    map['type'] = Variable<String>(type);\n    map['active'] = Variable<bool>(active);\n    map['name'] = Variable<String>(name);\n    if (!nullToAbsent || url != null) {\n      map['url'] = Variable<String>(url);\n    }\n    map['last_update'] = Variable<DateTime>(lastUpdate);\n    if (!nullToAbsent || updateInterval != null) {\n      map['update_interval'] = Variable<int>(updateInterval);\n    }\n    if (!nullToAbsent || upload != null) {\n      map['upload'] = Variable<int>(upload);\n    }\n    if (!nullToAbsent || download != null) {\n      map['download'] = Variable<int>(download);\n    }\n    if (!nullToAbsent || total != null) {\n      map['total'] = Variable<int>(total);\n    }\n    if (!nullToAbsent || expire != null) {\n      map['expire'] = Variable<DateTime>(expire);\n    }\n    if (!nullToAbsent || webPageUrl != null) {\n      map['web_page_url'] = Variable<String>(webPageUrl);\n    }\n    if (!nullToAbsent || supportUrl != null) {\n      map['support_url'] = Variable<String>(supportUrl);\n    }\n    if (!nullToAbsent || populatedHeaders != null) {\n      map['populated_headers'] = Variable<String>(populatedHeaders);\n    }\n    if (!nullToAbsent || profileOverride != null) {\n      map['profile_override'] = Variable<String>(profileOverride);\n    }\n    if (!nullToAbsent || userOverride != null) {\n      map['user_override'] = Variable<String>(userOverride);\n    }\n    return map;\n  }\n\n  ProfileEntriesCompanion toCompanion(bool nullToAbsent) {\n    return ProfileEntriesCompanion(\n      id: Value(id),\n      type: Value(type),\n      active: Value(active),\n      name: Value(name),\n      url: url == null && nullToAbsent ? const Value.absent() : Value(url),\n      lastUpdate: Value(lastUpdate),\n      updateInterval: updateInterval == null && nullToAbsent\n          ? const Value.absent()\n          : Value(updateInterval),\n      upload: upload == null && nullToAbsent\n          ? const Value.absent()\n          : Value(upload),\n      download: download == null && nullToAbsent\n          ? const Value.absent()\n          : Value(download),\n      total: total == null && nullToAbsent\n          ? const Value.absent()\n          : Value(total),\n      expire: expire == null && nullToAbsent\n          ? const Value.absent()\n          : Value(expire),\n      webPageUrl: webPageUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(webPageUrl),\n      supportUrl: supportUrl == null && nullToAbsent\n          ? const Value.absent()\n          : Value(supportUrl),\n      populatedHeaders: populatedHeaders == null && nullToAbsent\n          ? const Value.absent()\n          : Value(populatedHeaders),\n      profileOverride: profileOverride == null && nullToAbsent\n          ? const Value.absent()\n          : Value(profileOverride),\n      userOverride: userOverride == null && nullToAbsent\n          ? const Value.absent()\n          : Value(userOverride),\n    );\n  }\n\n  factory ProfileEntriesData.fromJson(\n    Map<String, dynamic> json, {\n    ValueSerializer? serializer,\n  }) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return ProfileEntriesData(\n      id: serializer.fromJson<String>(json['id']),\n      type: serializer.fromJson<String>(json['type']),\n      active: serializer.fromJson<bool>(json['active']),\n      name: serializer.fromJson<String>(json['name']),\n      url: serializer.fromJson<String?>(json['url']),\n      lastUpdate: serializer.fromJson<DateTime>(json['lastUpdate']),\n      updateInterval: serializer.fromJson<int?>(json['updateInterval']),\n      upload: serializer.fromJson<int?>(json['upload']),\n      download: serializer.fromJson<int?>(json['download']),\n      total: serializer.fromJson<int?>(json['total']),\n      expire: serializer.fromJson<DateTime?>(json['expire']),\n      webPageUrl: serializer.fromJson<String?>(json['webPageUrl']),\n      supportUrl: serializer.fromJson<String?>(json['supportUrl']),\n      populatedHeaders: serializer.fromJson<String?>(json['populatedHeaders']),\n      profileOverride: serializer.fromJson<String?>(json['profileOverride']),\n      userOverride: serializer.fromJson<String?>(json['userOverride']),\n    );\n  }\n  @override\n  Map<String, dynamic> toJson({ValueSerializer? serializer}) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return <String, dynamic>{\n      'id': serializer.toJson<String>(id),\n      'type': serializer.toJson<String>(type),\n      'active': serializer.toJson<bool>(active),\n      'name': serializer.toJson<String>(name),\n      'url': serializer.toJson<String?>(url),\n      'lastUpdate': serializer.toJson<DateTime>(lastUpdate),\n      'updateInterval': serializer.toJson<int?>(updateInterval),\n      'upload': serializer.toJson<int?>(upload),\n      'download': serializer.toJson<int?>(download),\n      'total': serializer.toJson<int?>(total),\n      'expire': serializer.toJson<DateTime?>(expire),\n      'webPageUrl': serializer.toJson<String?>(webPageUrl),\n      'supportUrl': serializer.toJson<String?>(supportUrl),\n      'populatedHeaders': serializer.toJson<String?>(populatedHeaders),\n      'profileOverride': serializer.toJson<String?>(profileOverride),\n      'userOverride': serializer.toJson<String?>(userOverride),\n    };\n  }\n\n  ProfileEntriesData copyWith({\n    String? id,\n    String? type,\n    bool? active,\n    String? name,\n    Value<String?> url = const Value.absent(),\n    DateTime? lastUpdate,\n    Value<int?> updateInterval = const Value.absent(),\n    Value<int?> upload = const Value.absent(),\n    Value<int?> download = const Value.absent(),\n    Value<int?> total = const Value.absent(),\n    Value<DateTime?> expire = const Value.absent(),\n    Value<String?> webPageUrl = const Value.absent(),\n    Value<String?> supportUrl = const Value.absent(),\n    Value<String?> populatedHeaders = const Value.absent(),\n    Value<String?> profileOverride = const Value.absent(),\n    Value<String?> userOverride = const Value.absent(),\n  }) => ProfileEntriesData(\n    id: id ?? this.id,\n    type: type ?? this.type,\n    active: active ?? this.active,\n    name: name ?? this.name,\n    url: url.present ? url.value : this.url,\n    lastUpdate: lastUpdate ?? this.lastUpdate,\n    updateInterval: updateInterval.present\n        ? updateInterval.value\n        : this.updateInterval,\n    upload: upload.present ? upload.value : this.upload,\n    download: download.present ? download.value : this.download,\n    total: total.present ? total.value : this.total,\n    expire: expire.present ? expire.value : this.expire,\n    webPageUrl: webPageUrl.present ? webPageUrl.value : this.webPageUrl,\n    supportUrl: supportUrl.present ? supportUrl.value : this.supportUrl,\n    populatedHeaders: populatedHeaders.present\n        ? populatedHeaders.value\n        : this.populatedHeaders,\n    profileOverride: profileOverride.present\n        ? profileOverride.value\n        : this.profileOverride,\n    userOverride: userOverride.present ? userOverride.value : this.userOverride,\n  );\n  ProfileEntriesData copyWithCompanion(ProfileEntriesCompanion data) {\n    return ProfileEntriesData(\n      id: data.id.present ? data.id.value : this.id,\n      type: data.type.present ? data.type.value : this.type,\n      active: data.active.present ? data.active.value : this.active,\n      name: data.name.present ? data.name.value : this.name,\n      url: data.url.present ? data.url.value : this.url,\n      lastUpdate: data.lastUpdate.present\n          ? data.lastUpdate.value\n          : this.lastUpdate,\n      updateInterval: data.updateInterval.present\n          ? data.updateInterval.value\n          : this.updateInterval,\n      upload: data.upload.present ? data.upload.value : this.upload,\n      download: data.download.present ? data.download.value : this.download,\n      total: data.total.present ? data.total.value : this.total,\n      expire: data.expire.present ? data.expire.value : this.expire,\n      webPageUrl: data.webPageUrl.present\n          ? data.webPageUrl.value\n          : this.webPageUrl,\n      supportUrl: data.supportUrl.present\n          ? data.supportUrl.value\n          : this.supportUrl,\n      populatedHeaders: data.populatedHeaders.present\n          ? data.populatedHeaders.value\n          : this.populatedHeaders,\n      profileOverride: data.profileOverride.present\n          ? data.profileOverride.value\n          : this.profileOverride,\n      userOverride: data.userOverride.present\n          ? data.userOverride.value\n          : this.userOverride,\n    );\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('ProfileEntriesData(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('url: $url, ')\n          ..write('lastUpdate: $lastUpdate, ')\n          ..write('updateInterval: $updateInterval, ')\n          ..write('upload: $upload, ')\n          ..write('download: $download, ')\n          ..write('total: $total, ')\n          ..write('expire: $expire, ')\n          ..write('webPageUrl: $webPageUrl, ')\n          ..write('supportUrl: $supportUrl, ')\n          ..write('populatedHeaders: $populatedHeaders, ')\n          ..write('profileOverride: $profileOverride, ')\n          ..write('userOverride: $userOverride')\n          ..write(')'))\n        .toString();\n  }\n\n  @override\n  int get hashCode => Object.hash(\n    id,\n    type,\n    active,\n    name,\n    url,\n    lastUpdate,\n    updateInterval,\n    upload,\n    download,\n    total,\n    expire,\n    webPageUrl,\n    supportUrl,\n    populatedHeaders,\n    profileOverride,\n    userOverride,\n  );\n  @override\n  bool operator ==(Object other) =>\n      identical(this, other) ||\n      (other is ProfileEntriesData &&\n          other.id == this.id &&\n          other.type == this.type &&\n          other.active == this.active &&\n          other.name == this.name &&\n          other.url == this.url &&\n          other.lastUpdate == this.lastUpdate &&\n          other.updateInterval == this.updateInterval &&\n          other.upload == this.upload &&\n          other.download == this.download &&\n          other.total == this.total &&\n          other.expire == this.expire &&\n          other.webPageUrl == this.webPageUrl &&\n          other.supportUrl == this.supportUrl &&\n          other.populatedHeaders == this.populatedHeaders &&\n          other.profileOverride == this.profileOverride &&\n          other.userOverride == this.userOverride);\n}\n\nclass ProfileEntriesCompanion extends UpdateCompanion<ProfileEntriesData> {\n  final Value<String> id;\n  final Value<String> type;\n  final Value<bool> active;\n  final Value<String> name;\n  final Value<String?> url;\n  final Value<DateTime> lastUpdate;\n  final Value<int?> updateInterval;\n  final Value<int?> upload;\n  final Value<int?> download;\n  final Value<int?> total;\n  final Value<DateTime?> expire;\n  final Value<String?> webPageUrl;\n  final Value<String?> supportUrl;\n  final Value<String?> populatedHeaders;\n  final Value<String?> profileOverride;\n  final Value<String?> userOverride;\n  final Value<int> rowid;\n  const ProfileEntriesCompanion({\n    this.id = const Value.absent(),\n    this.type = const Value.absent(),\n    this.active = const Value.absent(),\n    this.name = const Value.absent(),\n    this.url = const Value.absent(),\n    this.lastUpdate = const Value.absent(),\n    this.updateInterval = const Value.absent(),\n    this.upload = const Value.absent(),\n    this.download = const Value.absent(),\n    this.total = const Value.absent(),\n    this.expire = const Value.absent(),\n    this.webPageUrl = const Value.absent(),\n    this.supportUrl = const Value.absent(),\n    this.populatedHeaders = const Value.absent(),\n    this.profileOverride = const Value.absent(),\n    this.userOverride = const Value.absent(),\n    this.rowid = const Value.absent(),\n  });\n  ProfileEntriesCompanion.insert({\n    required String id,\n    required String type,\n    required bool active,\n    required String name,\n    this.url = const Value.absent(),\n    required DateTime lastUpdate,\n    this.updateInterval = const Value.absent(),\n    this.upload = const Value.absent(),\n    this.download = const Value.absent(),\n    this.total = const Value.absent(),\n    this.expire = const Value.absent(),\n    this.webPageUrl = const Value.absent(),\n    this.supportUrl = const Value.absent(),\n    this.populatedHeaders = const Value.absent(),\n    this.profileOverride = const Value.absent(),\n    this.userOverride = const Value.absent(),\n    this.rowid = const Value.absent(),\n  }) : id = Value(id),\n       type = Value(type),\n       active = Value(active),\n       name = Value(name),\n       lastUpdate = Value(lastUpdate);\n  static Insertable<ProfileEntriesData> custom({\n    Expression<String>? id,\n    Expression<String>? type,\n    Expression<bool>? active,\n    Expression<String>? name,\n    Expression<String>? url,\n    Expression<DateTime>? lastUpdate,\n    Expression<int>? updateInterval,\n    Expression<int>? upload,\n    Expression<int>? download,\n    Expression<int>? total,\n    Expression<DateTime>? expire,\n    Expression<String>? webPageUrl,\n    Expression<String>? supportUrl,\n    Expression<String>? populatedHeaders,\n    Expression<String>? profileOverride,\n    Expression<String>? userOverride,\n    Expression<int>? rowid,\n  }) {\n    return RawValuesInsertable({\n      if (id != null) 'id': id,\n      if (type != null) 'type': type,\n      if (active != null) 'active': active,\n      if (name != null) 'name': name,\n      if (url != null) 'url': url,\n      if (lastUpdate != null) 'last_update': lastUpdate,\n      if (updateInterval != null) 'update_interval': updateInterval,\n      if (upload != null) 'upload': upload,\n      if (download != null) 'download': download,\n      if (total != null) 'total': total,\n      if (expire != null) 'expire': expire,\n      if (webPageUrl != null) 'web_page_url': webPageUrl,\n      if (supportUrl != null) 'support_url': supportUrl,\n      if (populatedHeaders != null) 'populated_headers': populatedHeaders,\n      if (profileOverride != null) 'profile_override': profileOverride,\n      if (userOverride != null) 'user_override': userOverride,\n      if (rowid != null) 'rowid': rowid,\n    });\n  }\n\n  ProfileEntriesCompanion copyWith({\n    Value<String>? id,\n    Value<String>? type,\n    Value<bool>? active,\n    Value<String>? name,\n    Value<String?>? url,\n    Value<DateTime>? lastUpdate,\n    Value<int?>? updateInterval,\n    Value<int?>? upload,\n    Value<int?>? download,\n    Value<int?>? total,\n    Value<DateTime?>? expire,\n    Value<String?>? webPageUrl,\n    Value<String?>? supportUrl,\n    Value<String?>? populatedHeaders,\n    Value<String?>? profileOverride,\n    Value<String?>? userOverride,\n    Value<int>? rowid,\n  }) {\n    return ProfileEntriesCompanion(\n      id: id ?? this.id,\n      type: type ?? this.type,\n      active: active ?? this.active,\n      name: name ?? this.name,\n      url: url ?? this.url,\n      lastUpdate: lastUpdate ?? this.lastUpdate,\n      updateInterval: updateInterval ?? this.updateInterval,\n      upload: upload ?? this.upload,\n      download: download ?? this.download,\n      total: total ?? this.total,\n      expire: expire ?? this.expire,\n      webPageUrl: webPageUrl ?? this.webPageUrl,\n      supportUrl: supportUrl ?? this.supportUrl,\n      populatedHeaders: populatedHeaders ?? this.populatedHeaders,\n      profileOverride: profileOverride ?? this.profileOverride,\n      userOverride: userOverride ?? this.userOverride,\n      rowid: rowid ?? this.rowid,\n    );\n  }\n\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    if (id.present) {\n      map['id'] = Variable<String>(id.value);\n    }\n    if (type.present) {\n      map['type'] = Variable<String>(type.value);\n    }\n    if (active.present) {\n      map['active'] = Variable<bool>(active.value);\n    }\n    if (name.present) {\n      map['name'] = Variable<String>(name.value);\n    }\n    if (url.present) {\n      map['url'] = Variable<String>(url.value);\n    }\n    if (lastUpdate.present) {\n      map['last_update'] = Variable<DateTime>(lastUpdate.value);\n    }\n    if (updateInterval.present) {\n      map['update_interval'] = Variable<int>(updateInterval.value);\n    }\n    if (upload.present) {\n      map['upload'] = Variable<int>(upload.value);\n    }\n    if (download.present) {\n      map['download'] = Variable<int>(download.value);\n    }\n    if (total.present) {\n      map['total'] = Variable<int>(total.value);\n    }\n    if (expire.present) {\n      map['expire'] = Variable<DateTime>(expire.value);\n    }\n    if (webPageUrl.present) {\n      map['web_page_url'] = Variable<String>(webPageUrl.value);\n    }\n    if (supportUrl.present) {\n      map['support_url'] = Variable<String>(supportUrl.value);\n    }\n    if (populatedHeaders.present) {\n      map['populated_headers'] = Variable<String>(populatedHeaders.value);\n    }\n    if (profileOverride.present) {\n      map['profile_override'] = Variable<String>(profileOverride.value);\n    }\n    if (userOverride.present) {\n      map['user_override'] = Variable<String>(userOverride.value);\n    }\n    if (rowid.present) {\n      map['rowid'] = Variable<int>(rowid.value);\n    }\n    return map;\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('ProfileEntriesCompanion(')\n          ..write('id: $id, ')\n          ..write('type: $type, ')\n          ..write('active: $active, ')\n          ..write('name: $name, ')\n          ..write('url: $url, ')\n          ..write('lastUpdate: $lastUpdate, ')\n          ..write('updateInterval: $updateInterval, ')\n          ..write('upload: $upload, ')\n          ..write('download: $download, ')\n          ..write('total: $total, ')\n          ..write('expire: $expire, ')\n          ..write('webPageUrl: $webPageUrl, ')\n          ..write('supportUrl: $supportUrl, ')\n          ..write('populatedHeaders: $populatedHeaders, ')\n          ..write('profileOverride: $profileOverride, ')\n          ..write('userOverride: $userOverride, ')\n          ..write('rowid: $rowid')\n          ..write(')'))\n        .toString();\n  }\n}\n\nclass AppProxyEntries extends Table\n    with TableInfo<AppProxyEntries, AppProxyEntriesData> {\n  @override\n  final GeneratedDatabase attachedDatabase;\n  final String? _alias;\n  AppProxyEntries(this.attachedDatabase, [this._alias]);\n  late final GeneratedColumn<String> mode = GeneratedColumn<String>(\n    'mode',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<String> pkgName = GeneratedColumn<String>(\n    'pkg_name',\n    aliasedName,\n    false,\n    type: DriftSqlType.string,\n    requiredDuringInsert: true,\n  );\n  late final GeneratedColumn<int> flags = GeneratedColumn<int>(\n    'flags',\n    aliasedName,\n    false,\n    type: DriftSqlType.int,\n    requiredDuringInsert: false,\n    defaultValue: const CustomExpression('0'),\n  );\n  @override\n  List<GeneratedColumn> get $columns => [mode, pkgName, flags];\n  @override\n  String get aliasedName => _alias ?? actualTableName;\n  @override\n  String get actualTableName => $name;\n  static const String $name = 'app_proxy_entries';\n  @override\n  Set<GeneratedColumn> get $primaryKey => {mode, pkgName};\n  @override\n  AppProxyEntriesData map(Map<String, dynamic> data, {String? tablePrefix}) {\n    final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';\n    return AppProxyEntriesData(\n      mode: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}mode'],\n      )!,\n      pkgName: attachedDatabase.typeMapping.read(\n        DriftSqlType.string,\n        data['${effectivePrefix}pkg_name'],\n      )!,\n      flags: attachedDatabase.typeMapping.read(\n        DriftSqlType.int,\n        data['${effectivePrefix}flags'],\n      )!,\n    );\n  }\n\n  @override\n  AppProxyEntries createAlias(String alias) {\n    return AppProxyEntries(attachedDatabase, alias);\n  }\n}\n\nclass AppProxyEntriesData extends DataClass\n    implements Insertable<AppProxyEntriesData> {\n  final String mode;\n  final String pkgName;\n  final int flags;\n  const AppProxyEntriesData({\n    required this.mode,\n    required this.pkgName,\n    required this.flags,\n  });\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    map['mode'] = Variable<String>(mode);\n    map['pkg_name'] = Variable<String>(pkgName);\n    map['flags'] = Variable<int>(flags);\n    return map;\n  }\n\n  AppProxyEntriesCompanion toCompanion(bool nullToAbsent) {\n    return AppProxyEntriesCompanion(\n      mode: Value(mode),\n      pkgName: Value(pkgName),\n      flags: Value(flags),\n    );\n  }\n\n  factory AppProxyEntriesData.fromJson(\n    Map<String, dynamic> json, {\n    ValueSerializer? serializer,\n  }) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return AppProxyEntriesData(\n      mode: serializer.fromJson<String>(json['mode']),\n      pkgName: serializer.fromJson<String>(json['pkgName']),\n      flags: serializer.fromJson<int>(json['flags']),\n    );\n  }\n  @override\n  Map<String, dynamic> toJson({ValueSerializer? serializer}) {\n    serializer ??= driftRuntimeOptions.defaultSerializer;\n    return <String, dynamic>{\n      'mode': serializer.toJson<String>(mode),\n      'pkgName': serializer.toJson<String>(pkgName),\n      'flags': serializer.toJson<int>(flags),\n    };\n  }\n\n  AppProxyEntriesData copyWith({String? mode, String? pkgName, int? flags}) =>\n      AppProxyEntriesData(\n        mode: mode ?? this.mode,\n        pkgName: pkgName ?? this.pkgName,\n        flags: flags ?? this.flags,\n      );\n  AppProxyEntriesData copyWithCompanion(AppProxyEntriesCompanion data) {\n    return AppProxyEntriesData(\n      mode: data.mode.present ? data.mode.value : this.mode,\n      pkgName: data.pkgName.present ? data.pkgName.value : this.pkgName,\n      flags: data.flags.present ? data.flags.value : this.flags,\n    );\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('AppProxyEntriesData(')\n          ..write('mode: $mode, ')\n          ..write('pkgName: $pkgName, ')\n          ..write('flags: $flags')\n          ..write(')'))\n        .toString();\n  }\n\n  @override\n  int get hashCode => Object.hash(mode, pkgName, flags);\n  @override\n  bool operator ==(Object other) =>\n      identical(this, other) ||\n      (other is AppProxyEntriesData &&\n          other.mode == this.mode &&\n          other.pkgName == this.pkgName &&\n          other.flags == this.flags);\n}\n\nclass AppProxyEntriesCompanion extends UpdateCompanion<AppProxyEntriesData> {\n  final Value<String> mode;\n  final Value<String> pkgName;\n  final Value<int> flags;\n  final Value<int> rowid;\n  const AppProxyEntriesCompanion({\n    this.mode = const Value.absent(),\n    this.pkgName = const Value.absent(),\n    this.flags = const Value.absent(),\n    this.rowid = const Value.absent(),\n  });\n  AppProxyEntriesCompanion.insert({\n    required String mode,\n    required String pkgName,\n    this.flags = const Value.absent(),\n    this.rowid = const Value.absent(),\n  }) : mode = Value(mode),\n       pkgName = Value(pkgName);\n  static Insertable<AppProxyEntriesData> custom({\n    Expression<String>? mode,\n    Expression<String>? pkgName,\n    Expression<int>? flags,\n    Expression<int>? rowid,\n  }) {\n    return RawValuesInsertable({\n      if (mode != null) 'mode': mode,\n      if (pkgName != null) 'pkg_name': pkgName,\n      if (flags != null) 'flags': flags,\n      if (rowid != null) 'rowid': rowid,\n    });\n  }\n\n  AppProxyEntriesCompanion copyWith({\n    Value<String>? mode,\n    Value<String>? pkgName,\n    Value<int>? flags,\n    Value<int>? rowid,\n  }) {\n    return AppProxyEntriesCompanion(\n      mode: mode ?? this.mode,\n      pkgName: pkgName ?? this.pkgName,\n      flags: flags ?? this.flags,\n      rowid: rowid ?? this.rowid,\n    );\n  }\n\n  @override\n  Map<String, Expression> toColumns(bool nullToAbsent) {\n    final map = <String, Expression>{};\n    if (mode.present) {\n      map['mode'] = Variable<String>(mode.value);\n    }\n    if (pkgName.present) {\n      map['pkg_name'] = Variable<String>(pkgName.value);\n    }\n    if (flags.present) {\n      map['flags'] = Variable<int>(flags.value);\n    }\n    if (rowid.present) {\n      map['rowid'] = Variable<int>(rowid.value);\n    }\n    return map;\n  }\n\n  @override\n  String toString() {\n    return (StringBuffer('AppProxyEntriesCompanion(')\n          ..write('mode: $mode, ')\n          ..write('pkgName: $pkgName, ')\n          ..write('flags: $flags, ')\n          ..write('rowid: $rowid')\n          ..write(')'))\n        .toString();\n  }\n}\n\nclass DatabaseAtV5 extends GeneratedDatabase {\n  DatabaseAtV5(QueryExecutor e) : super(e);\n  late final ProfileEntries profileEntries = ProfileEntries(this);\n  late final AppProxyEntries appProxyEntries = AppProxyEntries(this);\n  @override\n  Iterable<TableInfo<Table, Object?>> get allTables =>\n      allSchemaEntities.whereType<TableInfo<Table, Object?>>();\n  @override\n  List<DatabaseSchemaEntity> get allSchemaEntities => [\n    profileEntries,\n    appProxyEntries,\n  ];\n  @override\n  int get schemaVersion => 5;\n  @override\n  DriftDatabaseOptions get options =>\n      const DriftDatabaseOptions(storeDateTimeAsText: true);\n}\n"
  },
  {
    "path": "test/drift/db/migration_test.dart",
    "content": "// dart format width=80\n// ignore_for_file: unused_local_variable, unused_import\nimport 'package:drift/drift.dart';\nimport 'package:drift_dev/api/migrations_native.dart';\nimport 'package:hiddify/core/db/db.dart';\nimport 'package:flutter_test/flutter_test.dart';\nimport 'generated/schema.dart';\n\nimport 'generated/schema_v1.dart' as v1;\nimport 'generated/schema_v2.dart' as v2;\nimport 'generated/schema_v3.dart' as v3;\nimport 'generated/schema_v4.dart' as v4;\n\nvoid main() {\n  driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;\n  late SchemaVerifier verifier;\n\n  setUpAll(() {\n    verifier = SchemaVerifier(GeneratedHelper());\n  });\n\n  group('simple database migrations', () {\n    // These simple tests verify all possible schema updates with a simple (no\n    // data) migration. This is a quick way to ensure that written database\n    // migrations properly alter the schema.\n    const versions = GeneratedHelper.versions;\n    for (final (i, fromVersion) in versions.indexed) {\n      group('from $fromVersion', () {\n        for (final toVersion in versions.skip(i + 1)) {\n          test('to $toVersion', () async {\n            final schema = await verifier.schemaAt(fromVersion);\n            final db = Db(schema.newConnection());\n            await verifier.migrateAndValidate(db, toVersion);\n            await db.close();\n          });\n        }\n      });\n    }\n  });\n\n  // The following template shows how to write tests ensuring your migrations\n  // preserve existing data.\n  // Testing this can be useful for migrations that change existing columns\n  // (e.g. by alterating their type or constraints). Migrations that only add\n  // tables or columns typically don't need these advanced tests. For more\n  // information, see https://drift.simonbinder.eu/migrations/tests/#verifying-data-integrity\n  // TODO: This generated template shows how these tests could be written. Adopt\n  // it to your own needs when testing migrations with data integrity.\n  test('migration from v1 to v2 does not corrupt data', () async {\n    // Add data to insert into the old database, and the expected rows after the\n    // migration.\n    // TODO: Fill these lists\n    final oldProfileEntriesData = <v1.ProfileEntriesData>[];\n    final expectedNewProfileEntriesData = <v2.ProfileEntriesData>[];\n\n    await verifier.testWithDataIntegrity(\n      oldVersion: 1,\n      newVersion: 2,\n      createOld: v1.DatabaseAtV1.new,\n      createNew: v2.DatabaseAtV2.new,\n      openTestedDatabase: Db.new,\n      createItems: (batch, oldDb) {\n        batch.insertAll(oldDb.profileEntries, oldProfileEntriesData);\n      },\n      validateItems: (newDb) async {\n        expect(\n          expectedNewProfileEntriesData,\n          await newDb.select(newDb.profileEntries).get(),\n        );\n      },\n    );\n  });\n\n  group('_columnExists-backed migrations', () {\n    test('migration from v3 to v4 adds test_url when missing', () async {\n      final schema = await verifier.schemaAt(3);\n      addTearDown(() => schema.rawDatabase.dispose());\n\n      final oldDb = v3.DatabaseAtV3(schema.newConnection());\n      final oldColumns = await oldDb\n          .customSelect('PRAGMA table_info(profile_entries);')\n          .get();\n\n      expect(\n        oldColumns.where((row) => row.data['name'] == 'test_url'),\n        isEmpty,\n      );\n      await oldDb.close();\n\n      final migratedDb = Db(schema.newConnection());\n      await verifier.migrateAndValidate(migratedDb, 4);\n      await migratedDb.close();\n\n      final newDb = v4.DatabaseAtV4(schema.newConnection());\n      final newColumns = await newDb\n          .customSelect('PRAGMA table_info(profile_entries);')\n          .get();\n      expect(\n        newColumns.where((row) => row.data['name'] == 'test_url'),\n        hasLength(1),\n      );\n      await newDb.close();\n    });\n\n    test(\n      'migration from v3 to v4 skips adding test_url when it already exists',\n      () async {\n        final schema = await verifier.schemaAt(3);\n        addTearDown(() => schema.rawDatabase.dispose());\n\n        schema.rawDatabase.execute(\n          'ALTER TABLE profile_entries ADD COLUMN test_url TEXT NULL;',\n        );\n\n        final migratedDb = Db(schema.newConnection());\n        await verifier.migrateAndValidate(migratedDb, 4);\n        await migratedDb.close();\n\n        final newDb = v4.DatabaseAtV4(schema.newConnection());\n        final newColumns = await newDb\n            .customSelect('PRAGMA table_info(profile_entries);')\n            .get();\n        expect(\n          newColumns.where((row) => row.data['name'] == 'test_url'),\n          hasLength(1),\n        );\n        await newDb.close();\n      },\n    );\n  });\n}\n"
  },
  {
    "path": "test/features/profile/data/profile_parser_test.dart",
    "content": "import 'package:flutter_test/flutter_test.dart';\nimport 'package:hiddify/features/profile/data/profile_parser.dart';\nimport 'package:hiddify/features/profile/model/profile_entity.dart';\nimport 'package:uuid/uuid.dart';\n\nvoid main() {\n  const validBaseUrl = \"https://example.com/configurations/user1/filename.yaml\";\n  const validExtendedUrl = \"https://example.com/configurations/user1/filename.yaml?test#b\";\n  const validSupportUrl = \"https://example.com/support\";\n\n  group(\"parse\", () {\n    test(\"Should use filename in url with no headers and fragment\", () {\n      final profile = ProfileParser.parse(\n        tempFilePath: '',\n        profile: ProfileEntity.remote(\n          id: const Uuid().v4(),\n          active: true,\n          name: '',\n          url: validBaseUrl,\n          lastUpdate: DateTime.now(),\n        ),\n      );\n      expect(profile.isRight(), true);\n      profile.match((l) {}, (r) {\n        expect(r is RemoteProfileEntity, true);\n        r.map(\n          remote: (rp) {\n            expect(rp.name, equals(\"filename\"));\n            expect(rp.url, equals(validBaseUrl));\n            expect(rp.options, isNull);\n            expect(rp.subInfo, isNull);\n          },\n          local: (lp) {},\n        );\n      });\n    });\n\n    test(\"Should use fragment in url with no headers\", () {\n      final profile = ProfileParser.parse(\n        tempFilePath: '',\n        profile: ProfileEntity.remote(\n          id: const Uuid().v4(),\n          active: true,\n          name: '',\n          url: validExtendedUrl,\n          lastUpdate: DateTime.now(),\n        ),\n      );\n      expect(profile.isRight(), true);\n      profile.match((l) {}, (r) {\n        expect(r is RemoteProfileEntity, true);\n        r.map(\n          remote: (rp) {\n            expect(rp.name, equals(\"b\"));\n            expect(rp.url, equals(validExtendedUrl));\n            expect(rp.options, isNull);\n            expect(rp.subInfo, isNull);\n          },\n          local: (lp) {},\n        );\n      });\n    });\n\n    test(\"Should use base64 title in headers\", () {\n      final headers = <String, List<String>>{\n        \"profile-title\": [\"base64:ZXhhbXBsZVRpdGxl\"],\n        \"profile-update-interval\": [\"1\"],\n        \"connection-test-url\": [validBaseUrl],\n        \"remote-dns-address\": [validBaseUrl],\n        \"subscription-userinfo\": [\"upload=0;download=1024;total=10240.5;expire=1704054600.55\"],\n        \"profile-web-page-url\": [validBaseUrl],\n        \"support-url\": [validSupportUrl],\n      };\n      // This fix occurs in the _downloadProfile method within ProfileParser, and the fixed headers are passed to populateHeaders\n      final fixedHeaders = headers.map((key, value) {\n        if (value.length == 1) return MapEntry(key, value.first);\n        return MapEntry(key, value);\n      });\n      final allHeaders = ProfileParser.populateHeaders(content: '', remoteHeaders: fixedHeaders);\n      expect(allHeaders.isRight(), true);\n      allHeaders.match((l) {}, (r) {\n        final profile = ProfileParser.parse(\n          tempFilePath: '',\n          profile: ProfileEntity.remote(\n            id: const Uuid().v4(),\n            active: true,\n            name: '',\n            url: validExtendedUrl,\n            lastUpdate: DateTime.now(),\n            populatedHeaders: r,\n          ),\n        );\n        expect(profile.isRight(), true);\n        profile.match((l) {}, (r) {\n          expect(r is RemoteProfileEntity, true);\n          r.map(\n            remote: (rp) {\n              expect(rp.name, equals(\"exampleTitle\"));\n              expect(rp.url, equals(validExtendedUrl));\n              expect(rp.options, equals(const ProfileOptions(updateInterval: Duration(hours: 1))));\n              expect(\n                rp.subInfo,\n                equals(\n                  SubscriptionInfo(\n                    upload: 0,\n                    download: 1024,\n                    total: 10240,\n                    expire: DateTime.fromMillisecondsSinceEpoch(1704054600 * 1000),\n                    webPageUrl: validBaseUrl,\n                    supportUrl: validSupportUrl,\n                  ),\n                ),\n              );\n            },\n            local: (lp) {},\n          );\n        });\n      });\n    });\n\n    test(\"Should use infinite when given 0 for subscription properties\", () {\n      final headers = <String, List<String>>{\n        \"profile-title\": [\"title\"],\n        \"profile-update-interval\": [\"1\"],\n        \"subscription-userinfo\": [\"upload=0;download=1024;total=0;expire=0\"],\n        \"profile-web-page-url\": [validBaseUrl],\n        \"support-url\": [validSupportUrl],\n      };\n      // This fix occurs in the _downloadProfile method within ProfileParser, and the fixed headers are passed to populateHeaders\n      final fixedHeaders = headers.map((key, value) {\n        if (value.length == 1) return MapEntry(key, value.first);\n        return MapEntry(key, value);\n      });\n      final allHeaders = ProfileParser.populateHeaders(content: '', remoteHeaders: fixedHeaders);\n      expect(allHeaders.isRight(), true);\n      allHeaders.match((l) {}, (r) {\n        final profile = ProfileParser.parse(\n          tempFilePath: '',\n          profile: RemoteProfileEntity(\n            id: const Uuid().v4(),\n            active: true,\n            name: '',\n            url: validBaseUrl,\n            lastUpdate: DateTime.now(),\n            populatedHeaders: r,\n          ),\n        );\n        expect(profile.isRight(), true);\n        profile.match((l) {}, (r) {\n          expect(r is RemoteProfileEntity, true);\n          r.map(\n            remote: (rp) {\n              expect(rp.subInfo, isNotNull);\n              expect(rp.subInfo!.total, equals(ProfileParser.infiniteTrafficThreshold + 1));\n              expect(\n                rp.subInfo!.expire,\n                equals(DateTime.fromMillisecondsSinceEpoch(ProfileParser.infiniteTimeThreshold * 1000)),\n              );\n            },\n            local: (lp) {},\n          );\n        });\n      });\n    });\n  });\n}\n"
  },
  {
    "path": "test.configs/README.md",
    "content": "# Add Warp Config\n\n## Step 1 مرحله\n\nYou need to install the Hiddify application from [our site](https://app.hiddify.com) or [GitHub](https://github.com/hiddify/hiddify-app/tree/main?tab=readme-ov-file#%EF%B8%8F-get-it-on-stores).\n\nشما باید ابتدا نرم‌افزار هیدیفای را از [سایت ما](https://app.hiddify.com) یا [گیت‌هاب](https://github.com/hiddify/hiddify-app/tree/main?tab=readme-ov-file#%EF%B8%8F-get-it-on-stores) دانلود کنید.\n\n## Step 2-1: Easy Way\n\nEasy Way but requires another VPN for first-time use\n[Click to Import Free Warp Config](https://app.hiddify.com/warp)\n\nراه ساده، اما نیاز به یک فیلترشکن دیگر برای اولین بار دارد.  [کلیک برای اتصال به کانفیگ رایگان](https://app.hiddify.com/warp)\n\n## Step 2-2: A More Advanced Way\n\nIf the previous step does not work, copy the following link and paste it into your Hiddify app.  \n\nاگر روش قبلی کار نکرد، لینک زیر را کپی کنید و مطابق تصویر به نرم‌افزار هیدیفای منتقل کنید.\n```\nhttps://raw.githubusercontent.com/hiddify/hiddify-app/refs/heads/main/test.configs/warp\n```\n![image](https://github.com/user-attachments/assets/2ad5a5d1-4c75-4b2d-b8b3-52a9f1e3e613)\n\n\n## Video\n[مشاهده فیلم آموزش See Guide Video](https://www.youtube.com/watch?v=Xv_7TDo80k4)\n"
  },
  {
    "path": "test.configs/ainita",
    "content": "#profile-title: base64:QWluaXRhLm5ldA==\n#profile-update-interval: 24\n#subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531\n#support-url: https://t.me/ainita\n#profile-web-page-url: https://ainita.net\n\nssconf://ainita.s3.eu-north-1.amazonaws.com/AinitaServer-1.csv\n\nssconf://ainita.s3.eu-north-1.amazonaws.com/AinitaServer-2.csv\n\nssconf://ainita.s3.eu-north-1.amazonaws.com/AinitaServer-3.csv\n\nssconf://ainita.s3.eu-north-1.amazonaws.com/AinitaServer-4.csv\n\n"
  },
  {
    "path": "test.configs/dnstt/dnstt_raw_config.json",
    "content": "\n{\n\"outbounds\": [\n    {\n      \"type\": \"dnstt\",\n      \"tag\": \"§hide§ § 0\",\n      \"publicKey\": \"publickey\",\n      \"domain\": \"yourdomain\",\n      \"resolvers\": [\n        \"8.8.8.8:53\",\n        \"8.8.4.4:53\",\n//add more dns server\n      ],\n      \"tunnel_per_resolver\": 40,\n      \"udp_over_tcp\": true\n    },\n    {\n      \"type\": \"socks\",\n      \"tag\": \"select\",\n      \"detour\": \"§hide§ § 0\",\n      \"server\": \"\",\n      \"server_port\": 0\n    },\n    {\n      \"type\": \"direct\",\n      \"tag\": \"direct §hide§\"\n    },\n    {\n      \"type\": \"direct\",\n      \"tag\": \"direct-fragment §hide§\",\n      \"tls_fragment\": {\n        \"enabled\": true,\n        \"size\": \"10-30\",\n        \"sleep\": \"2-8\"\n      }\n    }\n  ],\n\"inbounds\": [\n    {\n      \"type\": \"mixed\",\n      \"tag\": \"mixed-in127.0.0.1\",\n      \"listen\": \"127.0.0.1\",\n      \"listen_port\": 12334\n    },\n    {\n      \"type\": \"tproxy\",\n      \"tag\": \"tproxy-in127.0.0.1\",\n      \"listen\": \"127.0.0.1\",\n      \"listen_port\": 12335\n    },\n    {\n      \"type\": \"redirect\",\n      \"tag\": \"redirect-in127.0.0.1\",\n      \"listen\": \"127.0.0.1\",\n      \"listen_port\": 12336\n    },\n    {\n      \"type\": \"direct\",\n      \"tag\": \"dns-in127.0.0.1\",\n      \"listen\": \"127.0.0.1\",\n      \"listen_port\": 12337\n    }\n  ],\n\n  \"log\": {\n    \"level\": \"info\",\n    \"output\": \"data/box.log\"\n  },\n  \"dns\": {\n    \"servers\": [\n      {\n        \"type\": \"hosts\",\n        \"tag\": \"dns-static\"\n      },\n      {\n        \"type\": \"tcp\",\n        \"tag\": \"dns-remote\",\n        \"detour\": \"select\",\n        \"server\": \"1.1.1.1\"\n      },\n      {\n        \"type\": \"https\",\n        \"tag\": \"dns-remote-fallback\",\n        \"detour\": \"select\",\n        \"server\": \"8.8.8.8\",\n        \"tls\": {\n          \"enabled\": true\n        }\n      },\n      {\n        \"type\": \"https\",\n        \"tag\": \"dns-trick-direct\",\n        \"detour\": \"direct-fragment §hide§\",\n        \"domain_resolver\": {\n          \"server\": \"dns-direct\",\n          \"strategy\": \"prefer_ipv4\"\n        },\n        \"server\": \"dns.cloudflare.com\",\n        \"tls\": {\n          \"enabled\": true,\n          \"fragment\": true,\n          \"fragment_fallback_delay\": \"300ms\",\n          \"record_fragment\": true\n        }\n      },\n      {\n        \"type\": \"udp\",\n        \"tag\": \"dns-direct\",\n        \"connect_timeout\": \"5s\",\n        \"disable_tcp_keep_alive\": true,\n        \"server\": \"1.1.1.1\"\n      },\n      {\n        \"type\": \"local\",\n        \"tag\": \"dns-local\",\n        \"prefer_go\": true\n      },\n      {\n        \"type\": \"tcp\",\n        \"tag\": \"dns-remote-no-warp\",\n        \"detour\": \"direct-fragment §hide§\",\n        \"server\": \"1.1.1.1\"\n      },\n      {\n        \"type\": \"fakeip\",\n        \"tag\": \"dns-fake\",\n        \"inet4_range\": \"198.18.0.0/15\",\n        \"inet6_range\": \"fc00::/18\"\n      }\n    ],\n    \"rules\": [\n      {\n        \"domain\": \"api.cloudflareclient.com\",\n        \"server\": \"dns-remote-no-warp\",\n        \"rewrite_ttl\": 86400\n      },\n      {\n        \"domain\": [\n          \"captive.apple.com\",\n          \"cp.cloudflare.com\",\n          \"google.com\",\n          \"api.cloudflareclient.com\",\n          \"www.gstatic.com\"\n        ],\n        \"server\": \"dns-direct\",\n        \"rewrite_ttl\": 86400\n      },\n      {\n        \"domain_suffix\": \".ir\",\n        \"server\": \"dns-direct\",\n        \"rewrite_ttl\": 86400\n      },\n      {\n        \"rule_set\": \"geosite-ir\",\n        \"server\": \"dns-direct\",\n        \"rewrite_ttl\": 86400\n      },\n      {\n        \"query_type\": [\n          \"A\",\n          \"AAAA\"\n        ],\n        \"server\": \"dns-fake\",\n        \"disable_cache\": true,\n        \"rewrite_ttl\": 86400\n      },\n      {\n        \"server\": \"dns-remote\",\n        \"rewrite_ttl\": 86400\n      }\n    ],\n    \"final\": \"dns-remote\",\n    \"disable_expire\": true,\n    \"independent_cache\": true\n  },\n    \n  \"route\": {\n    \"rules\": [\n      {\n        \"action\": \"sniff\"\n      },\n      {\n        \"protocol\": \"dns\",\n        \"action\": \"hijack-dns\"\n      },\n      {\n        \"ip_cidr\": [\n          \"10.10.34.0/24\",\n          \"2001:4188:2:600:10:10:34:0/120\"\n        ],\n        \"outbound\": \"select\"\n      },\n      {\n        \"domain_suffix\": \".ir\",\n        \"outbound\": \"direct §hide§\"\n      },\n      {\n        \"rule_set\": [\n          \"geoip-ir\",\n          \"geosite-ir\"\n        ],\n        \"outbound\": \"direct §hide§\"\n      }\n    ],\n    \"rule_set\": [\n      {\n        \"type\": \"remote\",\n        \"tag\": \"geoip-ir\",\n        \"url\": \"https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/country/geoip-ir.srs\",\n        \"download_detour\": \"select\",\n        \"update_interval\": \"120h0m0s\"\n      },\n      {\n        \"type\": \"remote\",\n        \"tag\": \"geosite-ir\",\n        \"url\": \"https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/country/geosite-ir.srs\",\n        \"download_detour\": \"select\",\n        \"update_interval\": \"120h0m0s\"\n      }\n    ],\n    \"final\": \"select\",\n    \"default_domain_resolver\": \"dns-direct\"\n  }\n  \n}\n\n"
  },
  {
    "path": "test.configs/dnstt/readme.md",
    "content": "\n\n# for app:\n\n```\nsocks://#name -> dnstt://?tunnel_per_resolver=4&resolver=8.8.8.8:53&resolver=8.8.4.4:53&domain=dnstt.hiddify.com&publicKey=xxxx\n```\nor\n\n```\n{\n  \"outbounds\": [\n    {\n      \"type\": \"socks\",\n      \"tag\": \"socks\",\n      \"version\": \"5\",\n      \"detour\": \"dnstt1§hide§\"\n    },\n    {\n      \"type\": \"dnstt\",\n      \"tag\": \"dnstt1§hide§\",\n      \"publicKey\": \"xxxx\",\n      \"domain\": \"dnstt.hiddify.com\",\n      \"tunnel_per_resolver\": 4,\n      \"resolvers\": [\"8.8.8.8:53\", \"8.8.4.4:53\"]\n    }\n  ]\n}\n```\n\n\n\n# For cli or router or relay server:\ndownload hiddify core from:\nhttps://github.com/hiddify/hiddify-core/releases/\n\nthen you can run dnstt in router or relay server via\n\n```\nhiddify-core srun -c config.json\n```\n\nsee: dnstt_raw_config.json\n"
  },
  {
    "path": "test.configs/fragment",
    "content": "#profile-title: base64:8J+UpSBGcmFnbWVudCDwn5Sl\n#profile-update-interval: 24\n#subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531\n#support-url: https://t.me/hiddify\n#profile-web-page-url: https://hiddify.com\n#connection-test-url: https://instagram.com\n#remote-dns-address: https://sky.rethinkdns.com/dns-query\n\ndirect://?fragment=tlshello,10-100,100-200#Fragment1\ndirect://?fragment=tlshello,1-2,1-3#Fragment2\nxdirect://?fragment=tlshello,10-100,100-200#XFragment1\nxdirect://?fragment=tlshello,1-2,1-3#XFragment2\n\n\n"
  },
  {
    "path": "test.configs/free_configs",
    "content": "{\n\"profiles\":[\n  {\n    \"region\": [\"ir\", \"cn\", \"other\"],\n    \"title\": {\"en\": \"Warp & Psiphon\", \"fa\": \"وارپ و سایفون\"},\n    \"sublink\": \"https://raw.githubusercontent.com/hiddify/hiddify-app/refs/heads/main/test.configs/warp\",\n    \"tags\": { \"en\": [\"Warp\"], \"fa\": [\"وارپ\"] },\n    \"consent\": {\n        \"en\": \"Cloudflare WARP is a Free WireGuard VPN Provider. By enabling this option you are agreeing to the Cloudflare WARP's [Term of service](https://www.cloudflare.com/application/terms/) and [Privacy Policy](https://www.cloudflare.com/application/privacypolicy/).\",\n        \"fa\": \"وارپ کلودفلر یک ارائه دهنده رایگان وایرگارد است. با فعال کردن این گزینه، با [شرایط خدمات] (https://www.cloudflare.com/application/terms/) و [خط‌مشی رازداری] (https://www.cloudflare.com/application/) کلودفلر موافقت می‌کنید.\"\n    }\n  },\n  \n  {\n    \"region\": [\"ir\"],\n    \"title\": {\"en\": \"Anonymous 𝕏\", \"fa\": \"انونیموس 𝕏\"},\n    \"sublink\": \"https://raw.githubusercontent.com/4n0nymou3/multi-proxy-config-fetcher/refs/heads/main/configs/proxy_configs.txt\",\n    \"tags\": { \"en\": [\"mix\"], \"fa\": [\"عمومی\"] },\n    \"consent\": {\n      \"en\": \"This profile collects public and published configurations with the consent of their owners, and tests and verifies them to help the free flow of information.\\nTo enhance security, Hidify applies a Warp-based security layer to these configurations to prevent the risk of unauthorized access to information.\\nThere is no guarantee that this configuration will function properly and it is recommended to use it only in emergency situations.\",\n      \"fa\": \"این پروفایل کانفیگ‌های عمومی و منتشر شده را با رضایت صاحبان آن‌ها جمع آوری می‌کند و تست و بررسی می‌کند تا به گردش آزاد اطلاعات کمک کند.\\nبرای بالا بردن امنیت، هیدیفای یک لایه امنیتی مبتنی بر وارپ بر روی این کانفیگها اعمال میکند تا از خطر دسترسی غیرمجاز به اطلاعات جلوگیری کند.\\nهیچ ضمانتی برای عملکرد مناسب این کانفیگ وجود ندارد و پیشنهاد میشود صرفا در مواقع اضطراری از آن استفاده کنید\"\n    }\n  },\n{\n    \"region\": [\"ir\"],\n    \"title\": {\"en\": \"Mahsa\", \"fa\": \"مهسا\"},\n    \"sublink\": \"https://raw.githubusercontent.com/hiddify/hiddify-app/refs/heads/main/test.configs/mahsa\",\n    \"tags\": { \"en\": [\"mix\"], \"fa\": [\"عمومی\"] },\n    \"consent\": {\n      \"en\": \"This profile collects public and published configurations with the consent of their owners, and tests and verifies them to help the free flow of information.\\nTo enhance security, Hidify applies a Warp-based security layer to these configurations to prevent the risk of unauthorized access to information.\\nThere is no guarantee that this configuration will function properly and it is recommended to use it only in emergency situations.\",\n      \"fa\": \"این پروفایل کانفیگ‌های عمومی و منتشر شده را با رضایت صاحبان آن‌ها جمع آوری می‌کند و تست و بررسی می‌کند تا به گردش آزاد اطلاعات کمک کند.\\nبرای بالا بردن امنیت، هیدیفای یک لایه امنیتی مبتنی بر وارپ بر روی این کانفیگها اعمال میکند تا از خطر دسترسی غیرمجاز به اطلاعات جلوگیری کند.\\nهیچ ضمانتی برای عملکرد مناسب این کانفیگ وجود ندارد و پیشنهاد میشود صرفا در مواقع اضطراری از آن استفاده کنید\"\n    }\n  }\n]\n}\n"
  },
  {
    "path": "test.configs/mahsa",
    "content": "#profile-title: Mahsa\n#profile-update-interval: 24\n#subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531\n#support-url: https://github.com/mahsanet/MahsaFreeConfig\n#profile-web-page-url: https://github.com/mahsanet/MahsaFreeConfig\n\nhttps://raw.githubusercontent.com/mahsanet/MahsaFreeConfig/refs/heads/main/mci/sub_1.txt\nhttps://raw.githubusercontent.com/mahsanet/MahsaFreeConfig/refs/heads/main/mci/sub_2.txt\nhttps://raw.githubusercontent.com/mahsanet/MahsaFreeConfig/refs/heads/main/mci/sub_3.txt\nhttps://raw.githubusercontent.com/mahsanet/MahsaFreeConfig/refs/heads/main/mci/sub_4.txt\n\nhttps://raw.githubusercontent.com/mahsanet/MahsaFreeConfig/refs/heads/main/mtn/sub_1.txt\nhttps://raw.githubusercontent.com/mahsanet/MahsaFreeConfig/refs/heads/main/mtn/sub_2.txt\nhttps://raw.githubusercontent.com/mahsanet/MahsaFreeConfig/refs/heads/main/mtn/sub_3.txt\nhttps://raw.githubusercontent.com/mahsanet/MahsaFreeConfig/refs/heads/main/mtn/sub_4.txt\n"
  },
  {
    "path": "test.configs/super_fragment",
    "content": "#profile-title: base64:8J+UpSBTdXBlckZyYWdtZW50IPCflKU=\n#profile-update-interval: 24\n#subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531\n#support-url: https://t.me/hiddify\n#profile-web-page-url: https://hiddify.com\n#connection-test-url: https://instagram.com\n#remote-dns-address: https://dns.cloudflare.com/dns-query\n\n{\n  \"outbounds\": [\n    {\n      \"type\": \"xray\",\n      \"tag\": \"XSuperFragment\",\n      \"xconfig\": {\n        \"dns\": {\n          \"disableFallback\": true,\n          \"hosts\": {\n            \"dns.cloudflare.com\": \"cloudflare.com\"\n          },\n          \"servers\": [\n            \"https://dns.cloudflare.com/dns-query\",\n            {\"address\": \"1.1.1.1\", \"domains\": [\"full:cloudflare.com\"]},\n            {\"address\": \"223.5.5.5\", \"domains\": [\"full:cloudflare.com\"]}\n          ],\n          \"tag\": \"dns-query\"\n        },\n        \"outbounds\": [\n          {\n            \"domainStrategy\": \"AsIs\",\n            \"protocol\": \"freedom\",\n            \"streamSettings\": {\n              \"sockopt\": {\n                \"tcpKeepAliveIdle\": 100,\n                \"tcpNoDelay\": true\n              }\n            },\n            \"tag\": \"XFragment1\"\n          },\n          {\n            \"protocol\": \"blackhole\",\n            \"tag\": \"block\"\n          },\n          {\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"domainStrategy\": \"ForceIP\"\n            },\n            \"tag\": \"direct\"\n          },\n          {\n            \"protocol\": \"dns\",\n            \"streamSettings\": {\n              \"sockopt\": {\n                \"dialerProxy\": \"chain1-fragment\"\n              }\n            },\n            \"tag\": \"dns-out\"\n          },\n          {\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"fragment\": {\n                \"interval\": \"0\",\n                \"length\": \"6\",\n                \"packets\": \"tlshello\"\n              }\n            },\n            \"streamSettings\": {\n              \"sockopt\": {\n                \"dialerProxy\": \"chain1-fragment\"\n              }\n            },\n            \"tag\": \"super-fragment\"\n          },\n          {\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"fragment\": {\n                \"interval\": \"1\",\n                \"length\": \"517\",\n                \"packets\": \"1-3\"\n              }\n            },\n            \"streamSettings\": {\n              \"sockopt\": {\n                \"dialerProxy\": \"chain2-fragment\"\n              }\n            },\n            \"tag\": \"chain1-fragment\"\n          },\n          {\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"domainStrategy\": \"ForceIP\",\n              \"fragment\": {\n                \"interval\": \"2\",\n                \"length\": \"1\",\n                \"packets\": \"1-1\"\n              }\n            },\n            \"streamSettings\": {\n              \"sockopt\": {\n                \"tcpNoDelay\": true\n              }\n            },\n            \"tag\": \"chain2-fragment\"\n          },\n          {\n            \"tag\": \"udp-noisesv4\",\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"domainStrategy\": \"ForceIPv4\",\n              \"noises\": [\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}\n              ]\n            }            \n          },\n          {\n            \"tag\": \"udp-noisesv6\",\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"domainStrategy\": \"ForceIPv6\",\n              \"noises\": [\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}\n              ]\n            }            \n          }     \n        ],\n        \"routing\": {\n          \"domainStrategy\": \"IPOnDemand\",\n          \"rules\": [\n            {\n              \"inboundTag\": [\"dns-query\"],\n              \"network\": \"tcp\",\n              \"outboundTag\": \"super-fragment\"\n            },\n            {\n              \"ip\": [\"10.10.34.0/24\",\"2001:4188:2:600:10:10::/64\"],\n              \"outboundTag\": \"block\"\n            },\n            {\n              \"network\": \"udp\", \"port\": 443, \"ip\": [\"0.0.0.0/0\"], \n              \"outboundTag\": \"udp-noisesv4\"\n            },\n            {\n              \"network\": \"udp\", \"port\": 443, \"ip\": [\"::/0\"],\n              \"outboundTag\": \"udp-noisesv6\"\n            },\n            {\n              \"network\": \"udp\",\n              \"outboundTag\": \"direct\"\n            },\n            {\n              \"network\": \"tcp\",\n              \"outboundTag\": \"super-fragment\"\n            }\n          ]\n        }\n      },\n      \"xdebug\": false\n    },\n    {\n      \"type\": \"xray\",\n      \"tag\": \"XFragment\",\n      \"xconfig\": {\n        \"dns\": {\n          \"disableFallback\": true,\n          \"hosts\": {\n            \"dns.cloudflare.com\": \"cloudflare.com\"\n          },\n          \"servers\": [\n            \"https://dns.cloudflare.com/dns-query\",\n            {\"address\": \"1.1.1.1\", \"domains\": [\"full:cloudflare.com\"]},\n            {\"address\": \"223.5.5.5\", \"domains\": [\"full:cloudflare.com\"]}\n          ],\n          \"tag\": \"dns-query\"\n        },\n        \"outbounds\": [\n          {\n            \"domainStrategy\": \"AsIs\",\n            \"protocol\": \"freedom\",\n            \"streamSettings\": {\n              \"sockopt\": {\n                \"tcpKeepAliveIdle\": 100,\n                \"tcpNoDelay\": true\n              }\n            },\n            \"tag\": \"XFragment\"\n          },\n          {\n            \"protocol\": \"blackhole\",\n            \"tag\": \"block\"\n          },\n          {\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"domainStrategy\": \"ForceIP\"\n            },\n            \"tag\": \"direct\"\n          },\n          {\n            \"protocol\": \"dns\",\n            \"streamSettings\": {\n              \"sockopt\": {\n                \"dialerProxy\": \"chain1-fragment\"\n              }\n            },\n            \"tag\": \"dns-out\"\n          },\n          {\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"fragment\": {\n                \"interval\": \"0\",\n                \"length\": \"6\",\n                \"packets\": \"tlshello\"\n              }\n            },\n            \"streamSettings\": {\n              \"sockopt\": {\n                \"dialerProxy\": \"chain1-fragment\"\n              }\n            },\n            \"tag\": \"super-fragment\"\n          },\n          {\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"fragment\": {\n                \"interval\": \"1\",\n                \"length\": \"517\",\n                \"packets\": \"1-3\"\n              }\n            },\n            \"streamSettings\": {\n              \"sockopt\": {\n                \"dialerProxy\": \"chain2-fragment\"\n              }\n            },\n            \"tag\": \"chain1-fragment\"\n          },\n          {\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"domainStrategy\": \"ForceIP\",\n              \"fragment\": {\n                \"interval\": \"2\",\n                \"length\": \"1\",\n                \"packets\": \"1-1\"\n              }\n            },\n            \"streamSettings\": {\n              \"sockopt\": {\n                \"tcpNoDelay\": true\n              }\n            },\n            \"tag\": \"chain2-fragment\"\n          },\n          {\n            \"tag\": \"udp-noisesv4\",\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"domainStrategy\": \"ForceIPv4\",\n              \"noises\": [\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1250\", \"delay\": \"10\"}\n              ]\n            }            \n          },\n          {\n            \"tag\": \"udp-noisesv6\",\n            \"protocol\": \"freedom\",\n            \"settings\": {\n              \"domainStrategy\": \"ForceIPv6\",\n              \"noises\": [\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"},\n                {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}, {\"type\": \"rand\", \"packet\": \"1230\", \"delay\": \"10\"}\n              ]\n            }            \n          }     \n        ],\n        \"routing\": {\n          \"domainStrategy\": \"IPOnDemand\",\n          \"rules\": [\n            {\n              \"inboundTag\": [\"dns-query\"],\n              \"network\": \"tcp\",\n              \"outboundTag\": \"chain1-fragment\"\n            },\n            {\n              \"ip\": [\"10.10.34.0/24\",\"2001:4188:2:600:10:10::/64\"],\n              \"outboundTag\": \"block\"\n            },\n            {\n              \"network\": \"udp\", \"port\": 443, \"ip\": [\"0.0.0.0/0\"], \n              \"outboundTag\": \"udp-noisesv4\"\n            },\n            {\n              \"network\": \"udp\", \"port\": 443, \"ip\": [\"::/0\"],\n              \"outboundTag\": \"udp-noisesv6\"\n            },\n            {\n              \"network\": \"udp\",\n              \"outboundTag\": \"direct\"\n            },\n            {\n              \"network\": \"tcp\",\n              \"outboundTag\": \"chain1-fragment\"\n            }\n          ]\n        }\n      },\n      \"xdebug\": false\n    },\n    {\n      \"type\": \"direct\",\n      \"tag\": \"Fragment1 § 0\",\n      \"tls_fragment\": {\n        \"enabled\": true,\n        \"size\": \"1-2\",\n        \"sleep\": \"1-4\"\n      }\n    },\n    {\n      \"type\": \"direct\",\n      \"tag\": \"Fragment2 § 0\",\n      \"tls_fragment\": {\n        \"enabled\": true,\n        \"size\": \"10-100\",\n        \"sleep\": \"100-200\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "test.configs/warp",
    "content": "//profile-title: base64:8J+UpVBzaXBob24gJiBXQVJQIPCflKU=\n//profile-update-interval: 24\n//subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531\n//support-url: https://t.me/hiddify\n//profile-web-page-url: https://hiddify.com\n\npsiphon://auto/\n#psiphon://auto/?region=...&remote_server_list_url=...&remote_server_list_download_filename=...&remote_server_list_signature_public_key=...\nwarp://A1@188.114.97.170:894#warp_in_warp -> warp://A2@188.114.97.170:894?ifp=40-80&ifps=40-100&ifpd=4-8&ifpm=m4#m4 \nwarp://B1@auto#WarpInWarp✅ -> warp://B2@auto?ifpm=m4#LocalIP\n#warp://p1@ip1?ifp=1-3#WarpInWarp✅ -> warp://p2@ip2ifp=1-3#Warp🇮🇷IP\n\n#warp://auto?ifp=10-20&ifps=40-100&ifpd=10-20#Warp_10-20_40-100_10-20\n#warp://auto?ifp=10-20&ifps=40-100&ifpd=30-200#Warp_10-20_40-100_30-50\n#warp://auto?ifp=10-20&ifps=40-100&ifpd=300-500#Warp_10-20_40-100_300-500\n\n\n#warp://auto?ifp=5-10&ifps=40-100&ifpd=10-20#Warp_5-10_40-100_10-20\n#warp://auto?ifp=5-10&ifps=40-100&ifpd=30-50#Warp_5-10_40-100_30-50\n#warp://auto?ifp=5-10&ifps=40-100&ifpd=300-500#Warp_5-10_40-100_300-500\n\n\n\n"
  },
  {
    "path": "test.configs/warp2",
    "content": "//profile-title: base64:8J+UpSBXQVJQIPCflKU=\n//profile-update-interval: 24\n//subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531\n//support-url: https://t.me/hiddify\n//profile-web-page-url: https://hiddify.com\n\n#attention! do not use p1 and p2 in more than two configs otherwise confilicts may occure\n#ifpm is about mode we have currently 6 modes. \n\nwarp://p1@auto/?ifp=1-3&ifpm=m1#m1\nwarp://p2@auto/?ifp=1-3&ifpm=m2#m2\nwarp://p1@auto/?ifp=1-3&ifpm=m3#m3\nwarp://p2@auto/?ifp=1-3&ifpm=m4#m4\n\nwarp://p1@auto/?ifp=1-3&ifpm=m5#m5\nwarp://p2@auto/?ifp=1-3&ifpm=m6#m6\n\n#For g and h mode, you can use hex bytes between each _, with each part ranging from 00 to FF. You can also select more hex bytes to randomly choose between them.\n#In the next line, this means that the fake packet uses 0x30 as the first byte in the noise.\nwarp://p2@auto/?ifp=1-3&ifpm=h_30#h_30     \n#In the following line, g indicates that the fake packet randomly uses one of the values 0x10, 0x20, or 0x30 as the initial byte in the noise after the WireGuard reserved key. This should not be effective.\nwarp://p1@auto/?ifp=1-3&ifpm=g_10_20_30#g_10_20_30\n"
  },
  {
    "path": "web/drift_worker.js",
    "content": "(function dartProgram(){function copyProperties(a,b){var s=Object.keys(a)\nfor(var r=0;r<s.length;r++){var q=s[r]\nb[q]=a[q]}}function mixinPropertiesHard(a,b){var s=Object.keys(a)\nfor(var r=0;r<s.length;r++){var q=s[r]\nif(!b.hasOwnProperty(q)){b[q]=a[q]}}}function mixinPropertiesEasy(a,b){Object.assign(b,a)}var z=function(){var s=function(){}\ns.prototype={p:{}}\nvar r=new s()\nif(!(Object.getPrototypeOf(r)&&Object.getPrototypeOf(r).p===s.prototype.p))return false\ntry{if(typeof navigator!=\"undefined\"&&typeof navigator.userAgent==\"string\"&&navigator.userAgent.indexOf(\"Chrome/\")>=0)return true\nif(typeof version==\"function\"&&version.length==0){var q=version()\nif(/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(q))return true}}catch(p){}return false}()\nfunction inherit(a,b){a.prototype.constructor=a\na.prototype[\"$i\"+a.name]=a\nif(b!=null){if(z){Object.setPrototypeOf(a.prototype,b.prototype)\nreturn}var s=Object.create(b.prototype)\ncopyProperties(a.prototype,s)\na.prototype=s}}function inheritMany(a,b){for(var s=0;s<b.length;s++){inherit(b[s],a)}}function mixinEasy(a,b){mixinPropertiesEasy(b.prototype,a.prototype)\na.prototype.constructor=a}function mixinHard(a,b){mixinPropertiesHard(b.prototype,a.prototype)\na.prototype.constructor=a}function lazy(a,b,c,d){var s=a\na[b]=s\na[c]=function(){if(a[b]===s){a[b]=d()}a[c]=function(){return this[b]}\nreturn a[b]}}function lazyFinal(a,b,c,d){var s=a\na[b]=s\na[c]=function(){if(a[b]===s){var r=d()\nif(a[b]!==s){A.xB(b)}a[b]=r}var q=a[b]\na[c]=function(){return q}\nreturn q}}function makeConstList(a){a.immutable$list=Array\na.fixed$length=Array\nreturn a}function convertToFastObject(a){function t(){}t.prototype=a\nnew t()\nreturn a}function convertAllToFastObject(a){for(var s=0;s<a.length;++s){convertToFastObject(a[s])}}var y=0\nfunction instanceTearOffGetter(a,b){var s=null\nreturn a?function(c){if(s===null)s=A.pd(b)\nreturn new s(c,this)}:function(){if(s===null)s=A.pd(b)\nreturn new s(this,null)}}function staticTearOffGetter(a){var s=null\nreturn function(){if(s===null)s=A.pd(a).prototype\nreturn s}}var x=0\nfunction tearOffParameters(a,b,c,d,e,f,g,h,i,j){if(typeof h==\"number\"){h+=x}return{co:a,iS:b,iI:c,rC:d,dV:e,cs:f,fs:g,fT:h,aI:i||0,nDA:j}}function installStaticTearOff(a,b,c,d,e,f,g,h){var s=tearOffParameters(a,true,false,c,d,e,f,g,h,false)\nvar r=staticTearOffGetter(s)\na[b]=r}function installInstanceTearOff(a,b,c,d,e,f,g,h,i,j){c=!!c\nvar s=tearOffParameters(a,false,c,d,e,f,g,h,i,!!j)\nvar r=instanceTearOffGetter(c,s)\na[b]=r}function setOrUpdateInterceptorsByTag(a){var s=v.interceptorsByTag\nif(!s){v.interceptorsByTag=a\nreturn}copyProperties(a,s)}function setOrUpdateLeafTags(a){var s=v.leafTags\nif(!s){v.leafTags=a\nreturn}copyProperties(a,s)}function updateTypes(a){var s=v.types\nvar r=s.length\ns.push.apply(s,a)\nreturn r}function updateHolder(a,b){copyProperties(b,a)\nreturn a}var hunkHelpers=function(){var s=function(a,b,c,d,e){return function(f,g,h,i){return installInstanceTearOff(f,g,a,b,c,d,[h],i,e,false)}},r=function(a,b,c,d){return function(e,f,g,h){return installStaticTearOff(e,f,a,b,c,[g],h,d)}}\nreturn{inherit:inherit,inheritMany:inheritMany,mixin:mixinEasy,mixinHard:mixinHard,installStaticTearOff:installStaticTearOff,installInstanceTearOff:installInstanceTearOff,_instance_0u:s(0,0,null,[\"$0\"],0),_instance_1u:s(0,1,null,[\"$1\"],0),_instance_2u:s(0,2,null,[\"$2\"],0),_instance_0i:s(1,0,null,[\"$0\"],0),_instance_1i:s(1,1,null,[\"$1\"],0),_instance_2i:s(1,2,null,[\"$2\"],0),_static_0:r(0,null,[\"$0\"],0),_static_1:r(1,null,[\"$1\"],0),_static_2:r(2,null,[\"$2\"],0),makeConstList:makeConstList,lazy:lazy,lazyFinal:lazyFinal,updateHolder:updateHolder,convertToFastObject:convertToFastObject,updateTypes:updateTypes,setOrUpdateInterceptorsByTag:setOrUpdateInterceptorsByTag,setOrUpdateLeafTags:setOrUpdateLeafTags}}()\nfunction initializeDeferredHunk(a){x=v.types.length\na(hunkHelpers,v,w,$)}var J={\npl(a,b,c,d){return{i:a,p:b,e:c,x:d}},\nph(a){var s,r,q,p,o,n=a[v.dispatchPropertyName]\nif(n==null)if($.pj==null){A.x8()\nn=a[v.dispatchPropertyName]}if(n!=null){s=n.p\nif(!1===s)return n.i\nif(!0===s)return a\nr=Object.getPrototypeOf(a)\nif(s===r)return n.i\nif(n.e===r)throw A.a(A.qp(\"Return interceptor for \"+A.u(s(a,n))))}q=a.constructor\nif(q==null)p=null\nelse{o=$.nd\nif(o==null)o=$.nd=v.getIsolateTag(\"_$dart_js\")\np=q[o]}if(p!=null)return p\np=A.xf(a)\nif(p!=null)return p\nif(typeof a==\"function\")return B.aI\ns=Object.getPrototypeOf(a)\nif(s==null)return B.ag\nif(s===Object.prototype)return B.ag\nif(typeof q==\"function\"){o=$.nd\nif(o==null)o=$.nd=v.getIsolateTag(\"_$dart_js\")\nObject.defineProperty(q,o,{value:B.D,enumerable:false,writable:true,configurable:true})\nreturn B.D}return B.D},\npV(a,b){if(a<0||a>4294967295)throw A.a(A.a4(a,0,4294967295,\"length\",null))\nreturn J.uc(new Array(a),b)},\npW(a,b){if(a<0)throw A.a(A.K(\"Length must be a non-negative integer: \"+a,null))\nreturn A.d(new Array(a),b.h(\"w<0>\"))},\npU(a,b){if(a<0)throw A.a(A.K(\"Length must be a non-negative integer: \"+a,null))\nreturn A.d(new Array(a),b.h(\"w<0>\"))},\nuc(a,b){return J.k8(A.d(a,b.h(\"w<0>\")))},\nk8(a){a.fixed$length=Array\nreturn a},\nud(a,b){return J.tB(a,b)},\npX(a){if(a<256)switch(a){case 9:case 10:case 11:case 12:case 13:case 32:case 133:case 160:return!0\ndefault:return!1}switch(a){case 5760:case 8192:case 8193:case 8194:case 8195:case 8196:case 8197:case 8198:case 8199:case 8200:case 8201:case 8202:case 8232:case 8233:case 8239:case 8287:case 12288:case 65279:return!0\ndefault:return!1}},\nue(a,b){var s,r\nfor(s=a.length;b<s;){r=a.charCodeAt(b)\nif(r!==32&&r!==13&&!J.pX(r))break;++b}return b},\nuf(a,b){var s,r\nfor(;b>0;b=s){s=b-1\nr=a.charCodeAt(s)\nif(r!==32&&r!==13&&!J.pX(r))break}return b},\ncg(a){if(typeof a==\"number\"){if(Math.floor(a)==a)return J.ei.prototype\nreturn J.h9.prototype}if(typeof a==\"string\")return J.bV.prototype\nif(a==null)return J.ej.prototype\nif(typeof a==\"boolean\")return J.h8.prototype\nif(Array.isArray(a))return J.w.prototype\nif(typeof a!=\"object\"){if(typeof a==\"function\")return J.bW.prototype\nif(typeof a==\"symbol\")return J.el.prototype\nif(typeof a==\"bigint\")return J.aY.prototype\nreturn a}if(a instanceof A.e)return a\nreturn J.ph(a)},\nV(a){if(typeof a==\"string\")return J.bV.prototype\nif(a==null)return a\nif(Array.isArray(a))return J.w.prototype\nif(typeof a!=\"object\"){if(typeof a==\"function\")return J.bW.prototype\nif(typeof a==\"symbol\")return J.el.prototype\nif(typeof a==\"bigint\")return J.aY.prototype\nreturn a}if(a instanceof A.e)return a\nreturn J.ph(a)},\naM(a){if(a==null)return a\nif(Array.isArray(a))return J.w.prototype\nif(typeof a!=\"object\"){if(typeof a==\"function\")return J.bW.prototype\nif(typeof a==\"symbol\")return J.el.prototype\nif(typeof a==\"bigint\")return J.aY.prototype\nreturn a}if(a instanceof A.e)return a\nreturn J.ph(a)},\nx3(a){if(typeof a==\"number\")return J.cZ.prototype\nif(typeof a==\"string\")return J.bV.prototype\nif(a==null)return a\nif(!(a instanceof A.e))return J.cy.prototype\nreturn a},\nfs(a){if(typeof a==\"string\")return J.bV.prototype\nif(a==null)return a\nif(!(a instanceof A.e))return J.cy.prototype\nreturn a},\nX(a,b){if(a==null)return b==null\nif(typeof a!=\"object\")return b!=null&&a===b\nreturn J.cg(a).O(a,b)},\naO(a,b){if(typeof b===\"number\")if(Array.isArray(a)||typeof a==\"string\"||A.rE(a,a[v.dispatchPropertyName]))if(b>>>0===b&&b<a.length)return a[b]\nreturn J.V(a).i(a,b)},\npx(a,b,c){if(typeof b===\"number\")if((Array.isArray(a)||A.rE(a,a[v.dispatchPropertyName]))&&!a.immutable$list&&b>>>0===b&&b<a.length)return a[b]=c\nreturn J.aM(a).q(a,b,c)},\non(a,b){return J.aM(a).v(a,b)},\noo(a,b){return J.fs(a).ed(a,b)},\ntz(a,b,c){return J.fs(a).cM(a,b,c)},\npy(a,b){return J.aM(a).b8(a,b)},\ntA(a,b){return J.fs(a).jG(a,b)},\ntB(a,b){return J.x3(a).ag(a,b)},\npz(a,b){return J.V(a).M(a,b)},\nfx(a,b){return J.aM(a).N(a,b)},\ntC(a,b){return J.fs(a).ek(a,b)},\nfy(a){return J.aM(a).gG(a)},\naw(a){return J.cg(a).gB(a)},\niR(a){return J.V(a).gF(a)},\nM(a){return J.aM(a).gt(a)},\niS(a){return J.aM(a).gC(a)},\nae(a){return J.V(a).gl(a)},\ntD(a){return J.cg(a).gV(a)},\ntE(a,b,c){return J.aM(a).co(a,b,c)},\ncQ(a,b,c){return J.aM(a).bd(a,b,c)},\ntF(a,b,c){return J.fs(a).ha(a,b,c)},\ntG(a,b,c,d,e){return J.aM(a).Z(a,b,c,d,e)},\ndZ(a,b){return J.aM(a).X(a,b)},\ntH(a,b){return J.fs(a).u(a,b)},\ntI(a,b,c){return J.aM(a).a0(a,b,c)},\niT(a,b){return J.aM(a).ah(a,b)},\niU(a){return J.aM(a).cj(a)},\naU(a){return J.cg(a).j(a)},\nh7:function h7(){},\nh8:function h8(){},\nej:function ej(){},\nek:function ek(){},\nbY:function bY(){},\nhr:function hr(){},\ncy:function cy(){},\nbW:function bW(){},\naY:function aY(){},\nel:function el(){},\nw:function w(a){this.$ti=a},\nk9:function k9(a){this.$ti=a},\nfz:function fz(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=0\n_.d=null\n_.$ti=c},\ncZ:function cZ(){},\nei:function ei(){},\nh9:function h9(){},\nbV:function bV(){}},A={oA:function oA(){},\ne4(a,b,c){if(b.h(\"v<0>\").b(a))return new A.eS(a,b.h(\"@<0>\").H(c).h(\"eS<1,2>\"))\nreturn new A.ck(a,b.h(\"@<0>\").H(c).h(\"ck<1,2>\"))},\nug(a){return new A.bX(\"Field '\"+a+\"' has not been initialized.\")},\no5(a){var s,r=a^48\nif(r<=9)return r\ns=a|32\nif(97<=s&&s<=102)return s-87\nreturn-1},\nc6(a,b){a=a+b&536870911\na=a+((a&524287)<<10)&536870911\nreturn a^a>>>6},\noI(a){a=a+((a&67108863)<<3)&536870911\na^=a>>>11\nreturn a+((a&16383)<<15)&536870911},\naD(a,b,c){return a},\npk(a){var s,r\nfor(s=$.cO.length,r=0;r<s;++r)if(a===$.cO[r])return!0\nreturn!1},\nb3(a,b,c,d){A.ab(b,\"start\")\nif(c!=null){A.ab(c,\"end\")\nif(b>c)A.y(A.a4(b,0,c,\"start\",null))}return new A.cw(a,b,c,d.h(\"cw<0>\"))},\nen(a,b,c,d){if(t.Q.b(a))return new A.cp(a,b,c.h(\"@<0>\").H(d).h(\"cp<1,2>\"))\nreturn new A.az(a,b,c.h(\"@<0>\").H(d).h(\"az<1,2>\"))},\noJ(a,b,c){var s=\"takeCount\"\nA.bR(b,s)\nA.ab(b,s)\nif(t.Q.b(a))return new A.eb(a,b,c.h(\"eb<0>\"))\nreturn new A.cx(a,b,c.h(\"cx<0>\"))},\nqf(a,b,c){var s=\"count\"\nif(t.Q.b(a)){A.bR(b,s)\nA.ab(b,s)\nreturn new A.cV(a,b,c.h(\"cV<0>\"))}A.bR(b,s)\nA.ab(b,s)\nreturn new A.bB(a,b,c.h(\"bB<0>\"))},\nua(a,b,c){return new A.co(a,b,c.h(\"co<0>\"))},\nak(){return new A.b2(\"No element\")},\npT(){return new A.b2(\"Too few elements\")},\nca:function ca(){},\nfJ:function fJ(a,b){this.a=a\nthis.$ti=b},\nck:function ck(a,b){this.a=a\nthis.$ti=b},\neS:function eS(a,b){this.a=a\nthis.$ti=b},\neN:function eN(){},\nah:function ah(a,b){this.a=a\nthis.$ti=b},\nbX:function bX(a){this.a=a},\ne6:function e6(a){this.a=a},\noc:function oc(){},\nkB:function kB(){},\nv:function v(){},\nP:function P(){},\ncw:function cw(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.$ti=d},\naZ:function aZ(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=0\n_.d=null\n_.$ti=c},\naz:function az(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\ncp:function cp(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\nb0:function b0(a,b,c){var _=this\n_.a=null\n_.b=a\n_.c=b\n_.$ti=c},\nD:function D(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\naT:function aT(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\neH:function eH(a,b){this.a=a\nthis.b=b},\ned:function ed(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\nfY:function fY(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=null\n_.$ti=d},\ncx:function cx(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\neb:function eb(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\nhF:function hF(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\nbB:function bB(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\ncV:function cV(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\nhy:function hy(a,b){this.a=a\nthis.b=b},\nex:function ex(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\nhz:function hz(a,b){this.a=a\nthis.b=b\nthis.c=!1},\ncq:function cq(a){this.$ti=a},\nfV:function fV(){},\neI:function eI(a,b){this.a=a\nthis.$ti=b},\nhY:function hY(a,b){this.a=a\nthis.$ti=b},\nbt:function bt(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\nco:function co(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\neg:function eg(a,b){this.a=a\nthis.b=b\nthis.c=-1},\nee:function ee(){},\nhJ:function hJ(){},\ndh:function dh(){},\new:function ew(a,b){this.a=a\nthis.$ti=b},\nhE:function hE(a){this.a=a},\nfn:function fn(){},\nrO(a){var s=v.mangledGlobalNames[a]\nif(s!=null)return s\nreturn\"minified:\"+a},\nrE(a,b){var s\nif(b!=null){s=b.x\nif(s!=null)return s}return t.aU.b(a)},\nu(a){var s\nif(typeof a==\"string\")return a\nif(typeof a==\"number\"){if(a!==0)return\"\"+a}else if(!0===a)return\"true\"\nelse if(!1===a)return\"false\"\nelse if(a==null)return\"null\"\ns=J.aU(a)\nreturn s},\nev(a){var s,r=$.q3\nif(r==null)r=$.q3=Symbol(\"identityHashCode\")\ns=a[r]\nif(s==null){s=Math.random()*0x3fffffff|0\na[r]=s}return s},\nq4(a,b){var s,r,q,p,o,n=null,m=/^\\s*[+-]?((0x[a-f0-9]+)|(\\d+)|([a-z0-9]+))\\s*$/i.exec(a)\nif(m==null)return n\ns=m[3]\nif(b==null){if(s!=null)return parseInt(a,10)\nif(m[2]!=null)return parseInt(a,16)\nreturn n}if(b<2||b>36)throw A.a(A.a4(b,2,36,\"radix\",n))\nif(b===10&&s!=null)return parseInt(a,10)\nif(b<10||s==null){r=b<=10?47+b:86+b\nq=m[1]\nfor(p=q.length,o=0;o<p;++o)if((q.charCodeAt(o)|32)>r)return n}return parseInt(a,b)},\nkp(a){return A.uo(a)},\nuo(a){var s,r,q,p\nif(a instanceof A.e)return A.aK(A.aE(a),null)\ns=J.cg(a)\nif(s===B.aG||s===B.aJ||t.ak.b(a)){r=B.a1(a)\nif(r!==\"Object\"&&r!==\"\")return r\nq=a.constructor\nif(typeof q==\"function\"){p=q.name\nif(typeof p==\"string\"&&p!==\"Object\"&&p!==\"\")return p}}return A.aK(A.aE(a),null)},\nq5(a){if(a==null||typeof a==\"number\"||A.bM(a))return J.aU(a)\nif(typeof a==\"string\")return JSON.stringify(a)\nif(a instanceof A.cl)return a.j(0)\nif(a instanceof A.f6)return a.fP(!0)\nreturn\"Instance of '\"+A.kp(a)+\"'\"},\nup(){if(!!self.location)return self.location.href\nreturn null},\nq2(a){var s,r,q,p,o=a.length\nif(o<=500)return String.fromCharCode.apply(null,a)\nfor(s=\"\",r=0;r<o;r=q){q=r+500\np=q<o?q:o\ns+=String.fromCharCode.apply(null,a.slice(r,p))}return s},\nuy(a){var s,r,q,p=A.d([],t.t)\nfor(s=a.length,r=0;r<a.length;a.length===s||(0,A.W)(a),++r){q=a[r]\nif(!A.bn(q))throw A.a(A.dS(q))\nif(q<=65535)p.push(q)\nelse if(q<=1114111){p.push(55296+(B.b.P(q-65536,10)&1023))\np.push(56320+(q&1023))}else throw A.a(A.dS(q))}return A.q2(p)},\nq6(a){var s,r,q\nfor(s=a.length,r=0;r<s;++r){q=a[r]\nif(!A.bn(q))throw A.a(A.dS(q))\nif(q<0)throw A.a(A.dS(q))\nif(q>65535)return A.uy(a)}return A.q2(a)},\nuz(a,b,c){var s,r,q,p\nif(c<=500&&b===0&&c===a.length)return String.fromCharCode.apply(null,a)\nfor(s=b,r=\"\";s<c;s=q){q=s+500\np=q<c?q:c\nr+=String.fromCharCode.apply(null,a.subarray(s,p))}return r},\naA(a){var s\nif(0<=a){if(a<=65535)return String.fromCharCode(a)\nif(a<=1114111){s=a-65536\nreturn String.fromCharCode((B.b.P(s,10)|55296)>>>0,s&1023|56320)}}throw A.a(A.a4(a,0,1114111,null,null))},\naS(a){if(a.date===void 0)a.date=new Date(a.a)\nreturn a.date},\nux(a){return a.c?A.aS(a).getUTCFullYear()+0:A.aS(a).getFullYear()+0},\nuv(a){return a.c?A.aS(a).getUTCMonth()+1:A.aS(a).getMonth()+1},\nur(a){return a.c?A.aS(a).getUTCDate()+0:A.aS(a).getDate()+0},\nus(a){return a.c?A.aS(a).getUTCHours()+0:A.aS(a).getHours()+0},\nuu(a){return a.c?A.aS(a).getUTCMinutes()+0:A.aS(a).getMinutes()+0},\nuw(a){return a.c?A.aS(a).getUTCSeconds()+0:A.aS(a).getSeconds()+0},\nut(a){return a.c?A.aS(a).getUTCMilliseconds()+0:A.aS(a).getMilliseconds()+0},\nuq(a){var s=a.$thrownJsError\nif(s==null)return null\nreturn A.R(s)},\ndV(a,b){var s,r=\"index\"\nif(!A.bn(b))return new A.aV(!0,b,r,null)\ns=J.ae(a)\nif(b<0||b>=s)return A.h4(b,s,a,null,r)\nreturn A.kt(b,r)},\nwY(a,b,c){if(a>c)return A.a4(a,0,c,\"start\",null)\nif(b!=null)if(b<a||b>c)return A.a4(b,a,c,\"end\",null)\nreturn new A.aV(!0,b,\"end\",null)},\ndS(a){return new A.aV(!0,a,null,null)},\na(a){return A.rC(new Error(),a)},\nrC(a,b){var s\nif(b==null)b=new A.bD()\na.dartException=b\ns=A.xC\nif(\"defineProperty\" in Object){Object.defineProperty(a,\"message\",{get:s})\na.name=\"\"}else a.toString=s\nreturn a},\nxC(){return J.aU(this.dartException)},\ny(a){throw A.a(a)},\noi(a,b){throw A.rC(b,a)},\nW(a){throw A.a(A.ax(a))},\nbE(a){var s,r,q,p,o,n\na=A.rM(a.replace(String({}),\"$receiver$\"))\ns=a.match(/\\\\\\$[a-zA-Z]+\\\\\\$/g)\nif(s==null)s=A.d([],t.s)\nr=s.indexOf(\"\\\\$arguments\\\\$\")\nq=s.indexOf(\"\\\\$argumentsExpr\\\\$\")\np=s.indexOf(\"\\\\$expr\\\\$\")\no=s.indexOf(\"\\\\$method\\\\$\")\nn=s.indexOf(\"\\\\$receiver\\\\$\")\nreturn new A.lc(a.replace(new RegExp(\"\\\\\\\\\\\\$arguments\\\\\\\\\\\\$\",\"g\"),\"((?:x|[^x])*)\").replace(new RegExp(\"\\\\\\\\\\\\$argumentsExpr\\\\\\\\\\\\$\",\"g\"),\"((?:x|[^x])*)\").replace(new RegExp(\"\\\\\\\\\\\\$expr\\\\\\\\\\\\$\",\"g\"),\"((?:x|[^x])*)\").replace(new RegExp(\"\\\\\\\\\\\\$method\\\\\\\\\\\\$\",\"g\"),\"((?:x|[^x])*)\").replace(new RegExp(\"\\\\\\\\\\\\$receiver\\\\\\\\\\\\$\",\"g\"),\"((?:x|[^x])*)\"),r,q,p,o,n)},\nld(a){return function($expr$){var $argumentsExpr$=\"$arguments$\"\ntry{$expr$.$method$($argumentsExpr$)}catch(s){return s.message}}(a)},\nqo(a){return function($expr$){try{$expr$.$method$}catch(s){return s.message}}(a)},\noB(a,b){var s=b==null,r=s?null:b.method\nreturn new A.hb(a,r,s?null:b.receiver)},\nE(a){if(a==null)return new A.hp(a)\nif(a instanceof A.ec)return A.ch(a,a.a)\nif(typeof a!==\"object\")return a\nif(\"dartException\" in a)return A.ch(a,a.dartException)\nreturn A.wv(a)},\nch(a,b){if(t.w.b(b))if(b.$thrownJsError==null)b.$thrownJsError=a\nreturn b},\nwv(a){var s,r,q,p,o,n,m,l,k,j,i,h,g\nif(!(\"message\" in a))return a\ns=a.message\nif(\"number\" in a&&typeof a.number==\"number\"){r=a.number\nq=r&65535\nif((B.b.P(r,16)&8191)===10)switch(q){case 438:return A.ch(a,A.oB(A.u(s)+\" (Error \"+q+\")\",null))\ncase 445:case 5007:A.u(s)\nreturn A.ch(a,new A.er())}}if(a instanceof TypeError){p=$.rU()\no=$.rV()\nn=$.rW()\nm=$.rX()\nl=$.t_()\nk=$.t0()\nj=$.rZ()\n$.rY()\ni=$.t2()\nh=$.t1()\ng=p.ar(s)\nif(g!=null)return A.ch(a,A.oB(s,g))\nelse{g=o.ar(s)\nif(g!=null){g.method=\"call\"\nreturn A.ch(a,A.oB(s,g))}else if(n.ar(s)!=null||m.ar(s)!=null||l.ar(s)!=null||k.ar(s)!=null||j.ar(s)!=null||m.ar(s)!=null||i.ar(s)!=null||h.ar(s)!=null)return A.ch(a,new A.er())}return A.ch(a,new A.hI(typeof s==\"string\"?s:\"\"))}if(a instanceof RangeError){if(typeof s==\"string\"&&s.indexOf(\"call stack\")!==-1)return new A.eA()\ns=function(b){try{return String(b)}catch(f){}return null}(a)\nreturn A.ch(a,new A.aV(!1,null,null,typeof s==\"string\"?s.replace(/^RangeError:\\s*/,\"\"):s))}if(typeof InternalError==\"function\"&&a instanceof InternalError)if(typeof s==\"string\"&&s===\"too much recursion\")return new A.eA()\nreturn a},\nR(a){var s\nif(a instanceof A.ec)return a.b\nif(a==null)return new A.fa(a)\ns=a.$cachedTrace\nif(s!=null)return s\ns=new A.fa(a)\nif(typeof a===\"object\")a.$cachedTrace=s\nreturn s},\npm(a){if(a==null)return J.aw(a)\nif(typeof a==\"object\")return A.ev(a)\nreturn J.aw(a)},\nx_(a,b){var s,r,q,p=a.length\nfor(s=0;s<p;s=q){r=s+1\nq=r+1\nb.q(0,a[s],a[r])}return b},\nw_(a,b,c,d,e,f){switch(b){case 0:return a.$0()\ncase 1:return a.$1(c)\ncase 2:return a.$2(c,d)\ncase 3:return a.$3(c,d,e)\ncase 4:return a.$4(c,d,e,f)}throw A.a(A.jL(\"Unsupported number of arguments for wrapped closure\"))},\ncf(a,b){var s\nif(a==null)return null\ns=a.$identity\nif(!!s)return s\ns=A.wT(a,b)\na.$identity=s\nreturn s},\nwT(a,b){var s\nswitch(b){case 0:s=a.$0\nbreak\ncase 1:s=a.$1\nbreak\ncase 2:s=a.$2\nbreak\ncase 3:s=a.$3\nbreak\ncase 4:s=a.$4\nbreak\ndefault:s=null}if(s!=null)return s.bind(a)\nreturn function(c,d,e){return function(f,g,h,i){return e(c,d,f,g,h,i)}}(a,b,A.w_)},\ntT(a2){var s,r,q,p,o,n,m,l,k,j,i=a2.co,h=a2.iS,g=a2.iI,f=a2.nDA,e=a2.aI,d=a2.fs,c=a2.cs,b=d[0],a=c[0],a0=i[b],a1=a2.fT\na1.toString\ns=h?Object.create(new A.kT().constructor.prototype):Object.create(new A.e2(null,null).constructor.prototype)\ns.$initialize=s.constructor\nr=h?function static_tear_off(){this.$initialize()}:function tear_off(a3,a4){this.$initialize(a3,a4)}\ns.constructor=r\nr.prototype=s\ns.$_name=b\ns.$_target=a0\nq=!h\nif(q)p=A.pH(b,a0,g,f)\nelse{s.$static_name=b\np=a0}s.$S=A.tP(a1,h,g)\ns[a]=p\nfor(o=p,n=1;n<d.length;++n){m=d[n]\nif(typeof m==\"string\"){l=i[m]\nk=m\nm=l}else k=\"\"\nj=c[n]\nif(j!=null){if(q)m=A.pH(k,m,g,f)\ns[j]=m}if(n===e)o=m}s.$C=o\ns.$R=a2.rC\ns.$D=a2.dV\nreturn r},\ntP(a,b,c){if(typeof a==\"number\")return a\nif(typeof a==\"string\"){if(b)throw A.a(\"Cannot compute signature for static tearoff.\")\nreturn function(d,e){return function(){return e(this,d)}}(a,A.tM)}throw A.a(\"Error in functionType of tearoff\")},\ntQ(a,b,c,d){var s=A.pG\nswitch(b?-1:a){case 0:return function(e,f){return function(){return f(this)[e]()}}(c,s)\ncase 1:return function(e,f){return function(g){return f(this)[e](g)}}(c,s)\ncase 2:return function(e,f){return function(g,h){return f(this)[e](g,h)}}(c,s)\ncase 3:return function(e,f){return function(g,h,i){return f(this)[e](g,h,i)}}(c,s)\ncase 4:return function(e,f){return function(g,h,i,j){return f(this)[e](g,h,i,j)}}(c,s)\ncase 5:return function(e,f){return function(g,h,i,j,k){return f(this)[e](g,h,i,j,k)}}(c,s)\ndefault:return function(e,f){return function(){return e.apply(f(this),arguments)}}(d,s)}},\npH(a,b,c,d){if(c)return A.tS(a,b,d)\nreturn A.tQ(b.length,d,a,b)},\ntR(a,b,c,d){var s=A.pG,r=A.tN\nswitch(b?-1:a){case 0:throw A.a(new A.hv(\"Intercepted function with no arguments.\"))\ncase 1:return function(e,f,g){return function(){return f(this)[e](g(this))}}(c,r,s)\ncase 2:return function(e,f,g){return function(h){return f(this)[e](g(this),h)}}(c,r,s)\ncase 3:return function(e,f,g){return function(h,i){return f(this)[e](g(this),h,i)}}(c,r,s)\ncase 4:return function(e,f,g){return function(h,i,j){return f(this)[e](g(this),h,i,j)}}(c,r,s)\ncase 5:return function(e,f,g){return function(h,i,j,k){return f(this)[e](g(this),h,i,j,k)}}(c,r,s)\ncase 6:return function(e,f,g){return function(h,i,j,k,l){return f(this)[e](g(this),h,i,j,k,l)}}(c,r,s)\ndefault:return function(e,f,g){return function(){var q=[g(this)]\nArray.prototype.push.apply(q,arguments)\nreturn e.apply(f(this),q)}}(d,r,s)}},\ntS(a,b,c){var s,r\nif($.pE==null)$.pE=A.pD(\"interceptor\")\nif($.pF==null)$.pF=A.pD(\"receiver\")\ns=b.length\nr=A.tR(s,c,a,b)\nreturn r},\npd(a){return A.tT(a)},\ntM(a,b){return A.fi(v.typeUniverse,A.aE(a.a),b)},\npG(a){return a.a},\ntN(a){return a.b},\npD(a){var s,r,q,p=new A.e2(\"receiver\",\"interceptor\"),o=J.k8(Object.getOwnPropertyNames(p))\nfor(s=o.length,r=0;r<s;++r){q=o[r]\nif(p[q]===a)return q}throw A.a(A.K(\"Field name \"+a+\" not found.\",null))},\nyY(a){throw A.a(new A.i8(a))},\nx4(a){return v.getIsolateTag(a)},\nxF(a,b){var s=$.i\nif(s===B.d)return a\nreturn s.eg(a,b)},\nyS(a,b,c){Object.defineProperty(a,b,{value:c,enumerable:false,writable:true,configurable:true})},\nxf(a){var s,r,q,p,o,n=$.rB.$1(a),m=$.o3[n]\nif(m!=null){Object.defineProperty(a,v.dispatchPropertyName,{value:m,enumerable:false,writable:true,configurable:true})\nreturn m.i}s=$.o9[n]\nif(s!=null)return s\nr=v.interceptorsByTag[n]\nif(r==null){q=$.ru.$2(a,n)\nif(q!=null){m=$.o3[q]\nif(m!=null){Object.defineProperty(a,v.dispatchPropertyName,{value:m,enumerable:false,writable:true,configurable:true})\nreturn m.i}s=$.o9[q]\nif(s!=null)return s\nr=v.interceptorsByTag[q]\nn=q}}if(r==null)return null\ns=r.prototype\np=n[0]\nif(p===\"!\"){m=A.ob(s)\n$.o3[n]=m\nObject.defineProperty(a,v.dispatchPropertyName,{value:m,enumerable:false,writable:true,configurable:true})\nreturn m.i}if(p===\"~\"){$.o9[n]=s\nreturn s}if(p===\"-\"){o=A.ob(s)\nObject.defineProperty(Object.getPrototypeOf(a),v.dispatchPropertyName,{value:o,enumerable:false,writable:true,configurable:true})\nreturn o.i}if(p===\"+\")return A.rJ(a,s)\nif(p===\"*\")throw A.a(A.qp(n))\nif(v.leafTags[n]===true){o=A.ob(s)\nObject.defineProperty(Object.getPrototypeOf(a),v.dispatchPropertyName,{value:o,enumerable:false,writable:true,configurable:true})\nreturn o.i}else return A.rJ(a,s)},\nrJ(a,b){var s=Object.getPrototypeOf(a)\nObject.defineProperty(s,v.dispatchPropertyName,{value:J.pl(b,s,null,null),enumerable:false,writable:true,configurable:true})\nreturn b},\nob(a){return J.pl(a,!1,null,!!a.$iaP)},\nxh(a,b,c){var s=b.prototype\nif(v.leafTags[a]===true)return A.ob(s)\nelse return J.pl(s,c,null,null)},\nx8(){if(!0===$.pj)return\n$.pj=!0\nA.x9()},\nx9(){var s,r,q,p,o,n,m,l\n$.o3=Object.create(null)\n$.o9=Object.create(null)\nA.x7()\ns=v.interceptorsByTag\nr=Object.getOwnPropertyNames(s)\nif(typeof window!=\"undefined\"){window\nq=function(){}\nfor(p=0;p<r.length;++p){o=r[p]\nn=$.rL.$1(o)\nif(n!=null){m=A.xh(o,s[o],n)\nif(m!=null){Object.defineProperty(n,v.dispatchPropertyName,{value:m,enumerable:false,writable:true,configurable:true})\nq.prototype=n}}}}for(p=0;p<r.length;++p){o=r[p]\nif(/^[A-Za-z_]/.test(o)){l=s[o]\ns[\"!\"+o]=l\ns[\"~\"+o]=l\ns[\"-\"+o]=l\ns[\"+\"+o]=l\ns[\"*\"+o]=l}}},\nx7(){var s,r,q,p,o,n,m=B.at()\nm=A.dR(B.au,A.dR(B.av,A.dR(B.a2,A.dR(B.a2,A.dR(B.aw,A.dR(B.ax,A.dR(B.ay(B.a1),m)))))))\nif(typeof dartNativeDispatchHooksTransformer!=\"undefined\"){s=dartNativeDispatchHooksTransformer\nif(typeof s==\"function\")s=[s]\nif(Array.isArray(s))for(r=0;r<s.length;++r){q=s[r]\nif(typeof q==\"function\")m=q(m)||m}}p=m.getTag\no=m.getUnknownTag\nn=m.prototypeForTag\n$.rB=new A.o6(p)\n$.ru=new A.o7(o)\n$.rL=new A.o8(n)},\ndR(a,b){return a(b)||b},\nwW(a,b){var s=b.length,r=v.rttc[\"\"+s+\";\"+a]\nif(r==null)return null\nif(s===0)return r\nif(s===r.length)return r.apply(null,b)\nreturn r(b)},\noz(a,b,c,d,e,f){var s=b?\"m\":\"\",r=c?\"\":\"i\",q=d?\"u\":\"\",p=e?\"s\":\"\",o=f?\"g\":\"\",n=function(g,h){try{return new RegExp(g,h)}catch(m){return m}}(a,s+r+q+p+o)\nif(n instanceof RegExp)return n\nthrow A.a(A.ai(\"Illegal RegExp pattern (\"+String(n)+\")\",a,null))},\nxv(a,b,c){var s\nif(typeof b==\"string\")return a.indexOf(b,c)>=0\nelse if(b instanceof A.cs){s=B.a.K(a,c)\nreturn b.b.test(s)}else return!J.oo(b,B.a.K(a,c)).gF(0)},\npg(a){if(a.indexOf(\"$\",0)>=0)return a.replace(/\\$/g,\"$$$$\")\nreturn a},\nxy(a,b,c,d){var s=b.fe(a,d)\nif(s==null)return a\nreturn A.po(a,s.b.index,s.gby(),c)},\nrM(a){if(/[[\\]{}()*+?.\\\\^$|]/.test(a))return a.replace(/[[\\]{}()*+?.\\\\^$|]/g,\"\\\\$&\")\nreturn a},\nbc(a,b,c){var s\nif(typeof b==\"string\")return A.xx(a,b,c)\nif(b instanceof A.cs){s=b.gfq()\ns.lastIndex=0\nreturn a.replace(s,A.pg(c))}return A.xw(a,b,c)},\nxw(a,b,c){var s,r,q,p\nfor(s=J.oo(b,a),s=s.gt(s),r=0,q=\"\";s.k();){p=s.gm()\nq=q+a.substring(r,p.gcq())+c\nr=p.gby()}s=q+a.substring(r)\nreturn s.charCodeAt(0)==0?s:s},\nxx(a,b,c){var s,r,q\nif(b===\"\"){if(a===\"\")return c\ns=a.length\nr=\"\"+c\nfor(q=0;q<s;++q)r=r+a[q]+c\nreturn r.charCodeAt(0)==0?r:r}if(a.indexOf(b,0)<0)return a\nif(a.length<500||c.indexOf(\"$\",0)>=0)return a.split(b).join(c)\nreturn a.replace(new RegExp(A.rM(b),\"g\"),A.pg(c))},\nxz(a,b,c,d){var s,r,q,p\nif(typeof b==\"string\"){s=a.indexOf(b,d)\nif(s<0)return a\nreturn A.po(a,s,s+b.length,c)}if(b instanceof A.cs)return d===0?a.replace(b.b,A.pg(c)):A.xy(a,b,c,d)\nr=J.tz(b,a,d)\nq=r.gt(r)\nif(!q.k())return a\np=q.gm()\nreturn B.a.aO(a,p.gcq(),p.gby(),c)},\npo(a,b,c,d){return a.substring(0,b)+d+a.substring(c)},\nap:function ap(a,b){this.a=a\nthis.b=b},\ncH:function cH(a,b){this.a=a\nthis.b=b},\ne7:function e7(){},\ne8:function e8(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\ncG:function cG(a,b){this.a=a\nthis.$ti=b},\nil:function il(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=0\n_.d=null\n_.$ti=c},\nk3:function k3(){},\neh:function eh(a,b){this.a=a\nthis.$ti=b},\nlc:function lc(a,b,c,d,e,f){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f},\ner:function er(){},\nhb:function hb(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nhI:function hI(a){this.a=a},\nhp:function hp(a){this.a=a},\nec:function ec(a,b){this.a=a\nthis.b=b},\nfa:function fa(a){this.a=a\nthis.b=null},\ncl:function cl(){},\nj9:function j9(){},\nja:function ja(){},\nl2:function l2(){},\nkT:function kT(){},\ne2:function e2(a,b){this.a=a\nthis.b=b},\ni8:function i8(a){this.a=a},\nhv:function hv(a){this.a=a},\nbu:function bu(a){var _=this\n_.a=0\n_.f=_.e=_.d=_.c=_.b=null\n_.r=0\n_.$ti=a},\nkb:function kb(a){this.a=a},\nka:function ka(a){this.a=a},\nke:function ke(a,b){var _=this\n_.a=a\n_.b=b\n_.d=_.c=null},\nb8:function b8(a,b){this.a=a\nthis.$ti=b},\nhe:function he(a,b){var _=this\n_.a=a\n_.b=b\n_.d=_.c=null},\no6:function o6(a){this.a=a},\no7:function o7(a){this.a=a},\no8:function o8(a){this.a=a},\nf6:function f6(){},\nis:function is(){},\ncs:function cs(a,b){var _=this\n_.a=a\n_.b=b\n_.d=_.c=null},\ndz:function dz(a){this.b=a},\nhZ:function hZ(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nlO:function lO(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=null},\ndg:function dg(a,b){this.a=a\nthis.c=b},\niA:function iA(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nns:function ns(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=null},\nxB(a){A.oi(new A.bX(\"Field '\"+a+\"' has been assigned during initialization.\"),new Error())},\nG(){A.oi(new A.bX(\"Field '' has not been initialized.\"),new Error())},\npq(){A.oi(new A.bX(\"Field '' has already been initialized.\"),new Error())},\noj(){A.oi(new A.bX(\"Field '' has been assigned during initialization.\"),new Error())},\nm4(a){var s=new A.m3(a)\nreturn s.b=s},\nm3:function m3(a){this.a=a\nthis.b=null},\nvN(a){return a},\np5(a,b,c){},\niJ(a){var s,r,q\nif(t.aP.b(a))return a\ns=J.V(a)\nr=A.b_(s.gl(a),null,!1,t.z)\nfor(q=0;q<s.gl(a);++q)r[q]=s.i(a,q)\nreturn r},\nq_(a,b,c){var s\nA.p5(a,b,c)\ns=new DataView(a,b)\nreturn s},\nct(a,b,c){A.p5(a,b,c)\nc=B.b.I(a.byteLength-b,4)\nreturn new Int32Array(a,b,c)},\nun(a){return new Int8Array(a)},\nq0(a){return new Uint8Array(a)},\nbj(a,b,c){A.p5(a,b,c)\nreturn c==null?new Uint8Array(a,b):new Uint8Array(a,b,c)},\nbK(a,b,c){if(a>>>0!==a||a>=c)throw A.a(A.dV(b,a))},\nce(a,b,c){var s\nif(!(a>>>0!==a))s=b>>>0!==b||a>b||b>c\nelse s=!0\nif(s)throw A.a(A.wY(a,b,c))\nreturn b},\nd_:function d_(){},\nep:function ep(){},\nd0:function d0(){},\nd2:function d2(){},\nc_:function c_(){},\naR:function aR(){},\nhg:function hg(){},\nhh:function hh(){},\nhi:function hi(){},\nd1:function d1(){},\nhj:function hj(){},\nhk:function hk(){},\nhl:function hl(){},\neq:function eq(){},\nbx:function bx(){},\nf1:function f1(){},\nf2:function f2(){},\nf3:function f3(){},\nf4:function f4(){},\nqc(a,b){var s=b.c\nreturn s==null?b.c=A.p0(a,b.x,!0):s},\noE(a,b){var s=b.c\nreturn s==null?b.c=A.fg(a,\"C\",[b.x]):s},\nqd(a){var s=a.w\nif(s===6||s===7||s===8)return A.qd(a.x)\nreturn s===12||s===13},\nuB(a){return a.as},\naq(a){return A.iG(v.typeUniverse,a,!1)},\nxb(a,b){var s,r,q,p,o\nif(a==null)return null\ns=b.y\nr=a.Q\nif(r==null)r=a.Q=new Map()\nq=b.as\np=r.get(q)\nif(p!=null)return p\no=A.bN(v.typeUniverse,a.x,s,0)\nr.set(q,o)\nreturn o},\nbN(a1,a2,a3,a4){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0=a2.w\nswitch(a0){case 5:case 1:case 2:case 3:case 4:return a2\ncase 6:s=a2.x\nr=A.bN(a1,s,a3,a4)\nif(r===s)return a2\nreturn A.qS(a1,r,!0)\ncase 7:s=a2.x\nr=A.bN(a1,s,a3,a4)\nif(r===s)return a2\nreturn A.p0(a1,r,!0)\ncase 8:s=a2.x\nr=A.bN(a1,s,a3,a4)\nif(r===s)return a2\nreturn A.qQ(a1,r,!0)\ncase 9:q=a2.y\np=A.dP(a1,q,a3,a4)\nif(p===q)return a2\nreturn A.fg(a1,a2.x,p)\ncase 10:o=a2.x\nn=A.bN(a1,o,a3,a4)\nm=a2.y\nl=A.dP(a1,m,a3,a4)\nif(n===o&&l===m)return a2\nreturn A.oZ(a1,n,l)\ncase 11:k=a2.x\nj=a2.y\ni=A.dP(a1,j,a3,a4)\nif(i===j)return a2\nreturn A.qR(a1,k,i)\ncase 12:h=a2.x\ng=A.bN(a1,h,a3,a4)\nf=a2.y\ne=A.ws(a1,f,a3,a4)\nif(g===h&&e===f)return a2\nreturn A.qP(a1,g,e)\ncase 13:d=a2.y\na4+=d.length\nc=A.dP(a1,d,a3,a4)\no=a2.x\nn=A.bN(a1,o,a3,a4)\nif(c===d&&n===o)return a2\nreturn A.p_(a1,n,c,!0)\ncase 14:b=a2.x\nif(b<a4)return a2\na=a3[b-a4]\nif(a==null)return a2\nreturn a\ndefault:throw A.a(A.e_(\"Attempted to substitute unexpected RTI kind \"+a0))}},\ndP(a,b,c,d){var s,r,q,p,o=b.length,n=A.nG(o)\nfor(s=!1,r=0;r<o;++r){q=b[r]\np=A.bN(a,q,c,d)\nif(p!==q)s=!0\nn[r]=p}return s?n:b},\nwt(a,b,c,d){var s,r,q,p,o,n,m=b.length,l=A.nG(m)\nfor(s=!1,r=0;r<m;r+=3){q=b[r]\np=b[r+1]\no=b[r+2]\nn=A.bN(a,o,c,d)\nif(n!==o)s=!0\nl.splice(r,3,q,p,n)}return s?l:b},\nws(a,b,c,d){var s,r=b.a,q=A.dP(a,r,c,d),p=b.b,o=A.dP(a,p,c,d),n=b.c,m=A.wt(a,n,c,d)\nif(q===r&&o===p&&m===n)return b\ns=new A.ig()\ns.a=q\ns.b=o\ns.c=m\nreturn s},\nd(a,b){a[v.arrayRti]=b\nreturn a},\no0(a){var s=a.$S\nif(s!=null){if(typeof s==\"number\")return A.x6(s)\nreturn a.$S()}return null},\nxa(a,b){var s\nif(A.qd(b))if(a instanceof A.cl){s=A.o0(a)\nif(s!=null)return s}return A.aE(a)},\naE(a){if(a instanceof A.e)return A.t(a)\nif(Array.isArray(a))return A.Q(a)\nreturn A.p8(J.cg(a))},\nQ(a){var s=a[v.arrayRti],r=t.gn\nif(s==null)return r\nif(s.constructor!==r.constructor)return r\nreturn s},\nt(a){var s=a.$ti\nreturn s!=null?s:A.p8(a)},\np8(a){var s=a.constructor,r=s.$ccache\nif(r!=null)return r\nreturn A.vY(a,s)},\nvY(a,b){var s=a instanceof A.cl?Object.getPrototypeOf(Object.getPrototypeOf(a)).constructor:b,r=A.vl(v.typeUniverse,s.name)\nb.$ccache=r\nreturn r},\nx6(a){var s,r=v.types,q=r[a]\nif(typeof q==\"string\"){s=A.iG(v.typeUniverse,q,!1)\nr[a]=s\nreturn s}return q},\nx5(a){return A.bO(A.t(a))},\npi(a){var s=A.o0(a)\nreturn A.bO(s==null?A.aE(a):s)},\npc(a){var s\nif(a instanceof A.f6)return A.wZ(a.$r,a.fi())\ns=a instanceof A.cl?A.o0(a):null\nif(s!=null)return s\nif(t.dm.b(a))return J.tD(a).a\nif(Array.isArray(a))return A.Q(a)\nreturn A.aE(a)},\nbO(a){var s=a.r\nreturn s==null?a.r=A.r9(a):s},\nr9(a){var s,r,q=a.as,p=q.replace(/\\*/g,\"\")\nif(p===q)return a.r=new A.ny(a)\ns=A.iG(v.typeUniverse,p,!0)\nr=s.r\nreturn r==null?s.r=A.r9(s):r},\nwZ(a,b){var s,r,q=b,p=q.length\nif(p===0)return t.bQ\ns=A.fi(v.typeUniverse,A.pc(q[0]),\"@<0>\")\nfor(r=1;r<p;++r)s=A.qT(v.typeUniverse,s,A.pc(q[r]))\nreturn A.fi(v.typeUniverse,s,a)},\nbd(a){return A.bO(A.iG(v.typeUniverse,a,!1))},\nvX(a){var s,r,q,p,o,n,m=this\nif(m===t.K)return A.bL(m,a,A.w4)\nif(!A.bP(m))s=m===t._\nelse s=!0\nif(s)return A.bL(m,a,A.w8)\ns=m.w\nif(s===7)return A.bL(m,a,A.vV)\nif(s===1)return A.bL(m,a,A.rh)\nr=s===6?m.x:m\nq=r.w\nif(q===8)return A.bL(m,a,A.w0)\nif(r===t.S)p=A.bn\nelse if(r===t.i||r===t.v)p=A.w3\nelse if(r===t.N)p=A.w6\nelse p=r===t.y?A.bM:null\nif(p!=null)return A.bL(m,a,p)\nif(q===9){o=r.x\nif(r.y.every(A.xc)){m.f=\"$i\"+o\nif(o===\"q\")return A.bL(m,a,A.w2)\nreturn A.bL(m,a,A.w7)}}else if(q===11){n=A.wW(r.x,r.y)\nreturn A.bL(m,a,n==null?A.rh:n)}return A.bL(m,a,A.vT)},\nbL(a,b,c){a.b=c\nreturn a.b(b)},\nvW(a){var s,r=this,q=A.vS\nif(!A.bP(r))s=r===t._\nelse s=!0\nif(s)q=A.vD\nelse if(r===t.K)q=A.vB\nelse{s=A.ft(r)\nif(s)q=A.vU}r.a=q\nreturn r.a(a)},\niL(a){var s=a.w,r=!0\nif(!A.bP(a))if(!(a===t._))if(!(a===t.aw))if(s!==7)if(!(s===6&&A.iL(a.x)))r=s===8&&A.iL(a.x)||a===t.P||a===t.T\nreturn r},\nvT(a){var s=this\nif(a==null)return A.iL(s)\nreturn A.xd(v.typeUniverse,A.xa(a,s),s)},\nvV(a){if(a==null)return!0\nreturn this.x.b(a)},\nw7(a){var s,r=this\nif(a==null)return A.iL(r)\ns=r.f\nif(a instanceof A.e)return!!a[s]\nreturn!!J.cg(a)[s]},\nw2(a){var s,r=this\nif(a==null)return A.iL(r)\nif(typeof a!=\"object\")return!1\nif(Array.isArray(a))return!0\ns=r.f\nif(a instanceof A.e)return!!a[s]\nreturn!!J.cg(a)[s]},\nvS(a){var s=this\nif(a==null){if(A.ft(s))return a}else if(s.b(a))return a\nA.re(a,s)},\nvU(a){var s=this\nif(a==null)return a\nelse if(s.b(a))return a\nA.re(a,s)},\nre(a,b){throw A.a(A.vc(A.qG(a,A.aK(b,null))))},\nqG(a,b){return A.fX(a)+\": type '\"+A.aK(A.pc(a),null)+\"' is not a subtype of type '\"+b+\"'\"},\nvc(a){return new A.fe(\"TypeError: \"+a)},\naC(a,b){return new A.fe(\"TypeError: \"+A.qG(a,b))},\nw0(a){var s=this,r=s.w===6?s.x:s\nreturn r.x.b(a)||A.oE(v.typeUniverse,r).b(a)},\nw4(a){return a!=null},\nvB(a){if(a!=null)return a\nthrow A.a(A.aC(a,\"Object\"))},\nw8(a){return!0},\nvD(a){return a},\nrh(a){return!1},\nbM(a){return!0===a||!1===a},\nbJ(a){if(!0===a)return!0\nif(!1===a)return!1\nthrow A.a(A.aC(a,\"bool\"))},\nyn(a){if(!0===a)return!0\nif(!1===a)return!1\nif(a==null)return a\nthrow A.a(A.aC(a,\"bool\"))},\nym(a){if(!0===a)return!0\nif(!1===a)return!1\nif(a==null)return a\nthrow A.a(A.aC(a,\"bool?\"))},\nr(a){if(typeof a==\"number\")return a\nthrow A.a(A.aC(a,\"double\"))},\nyp(a){if(typeof a==\"number\")return a\nif(a==null)return a\nthrow A.a(A.aC(a,\"double\"))},\nyo(a){if(typeof a==\"number\")return a\nif(a==null)return a\nthrow A.a(A.aC(a,\"double?\"))},\nbn(a){return typeof a==\"number\"&&Math.floor(a)===a},\nh(a){if(typeof a==\"number\"&&Math.floor(a)===a)return a\nthrow A.a(A.aC(a,\"int\"))},\nyr(a){if(typeof a==\"number\"&&Math.floor(a)===a)return a\nif(a==null)return a\nthrow A.a(A.aC(a,\"int\"))},\nyq(a){if(typeof a==\"number\"&&Math.floor(a)===a)return a\nif(a==null)return a\nthrow A.a(A.aC(a,\"int?\"))},\nw3(a){return typeof a==\"number\"},\nys(a){if(typeof a==\"number\")return a\nthrow A.a(A.aC(a,\"num\"))},\nyu(a){if(typeof a==\"number\")return a\nif(a==null)return a\nthrow A.a(A.aC(a,\"num\"))},\nyt(a){if(typeof a==\"number\")return a\nif(a==null)return a\nthrow A.a(A.aC(a,\"num?\"))},\nw6(a){return typeof a==\"string\"},\nad(a){if(typeof a==\"string\")return a\nthrow A.a(A.aC(a,\"String\"))},\nyv(a){if(typeof a==\"string\")return a\nif(a==null)return a\nthrow A.a(A.aC(a,\"String\"))},\nvC(a){if(typeof a==\"string\")return a\nif(a==null)return a\nthrow A.a(A.aC(a,\"String?\"))},\nro(a,b){var s,r,q\nfor(s=\"\",r=\"\",q=0;q<a.length;++q,r=\", \")s+=r+A.aK(a[q],b)\nreturn s},\nwg(a,b){var s,r,q,p,o,n,m=a.x,l=a.y\nif(\"\"===m)return\"(\"+A.ro(l,b)+\")\"\ns=l.length\nr=m.split(\",\")\nq=r.length-s\nfor(p=\"(\",o=\"\",n=0;n<s;++n,o=\", \"){p+=o\nif(q===0)p+=\"{\"\np+=A.aK(l[n],b)\nif(q>=0)p+=\" \"+r[q];++q}return p+\"})\"},\nrf(a3,a4,a5){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1=\", \",a2=null\nif(a5!=null){s=a5.length\nif(a4==null)a4=A.d([],t.s)\nelse a2=a4.length\nr=a4.length\nfor(q=s;q>0;--q)a4.push(\"T\"+(r+q))\nfor(p=t.X,o=t._,n=\"<\",m=\"\",q=0;q<s;++q,m=a1){n=B.a.dh(n+m,a4[a4.length-1-q])\nl=a5[q]\nk=l.w\nif(!(k===2||k===3||k===4||k===5||l===p))j=l===o\nelse j=!0\nif(!j)n+=\" extends \"+A.aK(l,a4)}n+=\">\"}else n=\"\"\np=a3.x\ni=a3.y\nh=i.a\ng=h.length\nf=i.b\ne=f.length\nd=i.c\nc=d.length\nb=A.aK(p,a4)\nfor(a=\"\",a0=\"\",q=0;q<g;++q,a0=a1)a+=a0+A.aK(h[q],a4)\nif(e>0){a+=a0+\"[\"\nfor(a0=\"\",q=0;q<e;++q,a0=a1)a+=a0+A.aK(f[q],a4)\na+=\"]\"}if(c>0){a+=a0+\"{\"\nfor(a0=\"\",q=0;q<c;q+=3,a0=a1){a+=a0\nif(d[q+1])a+=\"required \"\na+=A.aK(d[q+2],a4)+\" \"+d[q]}a+=\"}\"}if(a2!=null){a4.toString\na4.length=a2}return n+\"(\"+a+\") => \"+b},\naK(a,b){var s,r,q,p,o,n,m=a.w\nif(m===5)return\"erased\"\nif(m===2)return\"dynamic\"\nif(m===3)return\"void\"\nif(m===1)return\"Never\"\nif(m===4)return\"any\"\nif(m===6)return A.aK(a.x,b)\nif(m===7){s=a.x\nr=A.aK(s,b)\nq=s.w\nreturn(q===12||q===13?\"(\"+r+\")\":r)+\"?\"}if(m===8)return\"FutureOr<\"+A.aK(a.x,b)+\">\"\nif(m===9){p=A.wu(a.x)\no=a.y\nreturn o.length>0?p+(\"<\"+A.ro(o,b)+\">\"):p}if(m===11)return A.wg(a,b)\nif(m===12)return A.rf(a,b,null)\nif(m===13)return A.rf(a.x,b,a.y)\nif(m===14){n=a.x\nreturn b[b.length-1-n]}return\"?\"},\nwu(a){var s=v.mangledGlobalNames[a]\nif(s!=null)return s\nreturn\"minified:\"+a},\nvm(a,b){var s=a.tR[b]\nfor(;typeof s==\"string\";)s=a.tR[s]\nreturn s},\nvl(a,b){var s,r,q,p,o,n=a.eT,m=n[b]\nif(m==null)return A.iG(a,b,!1)\nelse if(typeof m==\"number\"){s=m\nr=A.fh(a,5,\"#\")\nq=A.nG(s)\nfor(p=0;p<s;++p)q[p]=r\no=A.fg(a,b,q)\nn[b]=o\nreturn o}else return m},\nvk(a,b){return A.r6(a.tR,b)},\nvj(a,b){return A.r6(a.eT,b)},\niG(a,b,c){var s,r=a.eC,q=r.get(b)\nif(q!=null)return q\ns=A.qL(A.qJ(a,null,b,c))\nr.set(b,s)\nreturn s},\nfi(a,b,c){var s,r,q=b.z\nif(q==null)q=b.z=new Map()\ns=q.get(c)\nif(s!=null)return s\nr=A.qL(A.qJ(a,b,c,!0))\nq.set(c,r)\nreturn r},\nqT(a,b,c){var s,r,q,p=b.Q\nif(p==null)p=b.Q=new Map()\ns=c.as\nr=p.get(s)\nif(r!=null)return r\nq=A.oZ(a,b,c.w===10?c.y:[c])\np.set(s,q)\nreturn q},\nbI(a,b){b.a=A.vW\nb.b=A.vX\nreturn b},\nfh(a,b,c){var s,r,q=a.eC.get(c)\nif(q!=null)return q\ns=new A.b1(null,null)\ns.w=b\ns.as=c\nr=A.bI(a,s)\na.eC.set(c,r)\nreturn r},\nqS(a,b,c){var s,r=b.as+\"*\",q=a.eC.get(r)\nif(q!=null)return q\ns=A.vh(a,b,r,c)\na.eC.set(r,s)\nreturn s},\nvh(a,b,c,d){var s,r,q\nif(d){s=b.w\nif(!A.bP(b))r=b===t.P||b===t.T||s===7||s===6\nelse r=!0\nif(r)return b}q=new A.b1(null,null)\nq.w=6\nq.x=b\nq.as=c\nreturn A.bI(a,q)},\np0(a,b,c){var s,r=b.as+\"?\",q=a.eC.get(r)\nif(q!=null)return q\ns=A.vg(a,b,r,c)\na.eC.set(r,s)\nreturn s},\nvg(a,b,c,d){var s,r,q,p\nif(d){s=b.w\nr=!0\nif(!A.bP(b))if(!(b===t.P||b===t.T))if(s!==7)r=s===8&&A.ft(b.x)\nif(r)return b\nelse if(s===1||b===t.aw)return t.P\nelse if(s===6){q=b.x\nif(q.w===8&&A.ft(q.x))return q\nelse return A.qc(a,b)}}p=new A.b1(null,null)\np.w=7\np.x=b\np.as=c\nreturn A.bI(a,p)},\nqQ(a,b,c){var s,r=b.as+\"/\",q=a.eC.get(r)\nif(q!=null)return q\ns=A.ve(a,b,r,c)\na.eC.set(r,s)\nreturn s},\nve(a,b,c,d){var s,r\nif(d){s=b.w\nif(A.bP(b)||b===t.K||b===t._)return b\nelse if(s===1)return A.fg(a,\"C\",[b])\nelse if(b===t.P||b===t.T)return t.eH}r=new A.b1(null,null)\nr.w=8\nr.x=b\nr.as=c\nreturn A.bI(a,r)},\nvi(a,b){var s,r,q=\"\"+b+\"^\",p=a.eC.get(q)\nif(p!=null)return p\ns=new A.b1(null,null)\ns.w=14\ns.x=b\ns.as=q\nr=A.bI(a,s)\na.eC.set(q,r)\nreturn r},\nff(a){var s,r,q,p=a.length\nfor(s=\"\",r=\"\",q=0;q<p;++q,r=\",\")s+=r+a[q].as\nreturn s},\nvd(a){var s,r,q,p,o,n=a.length\nfor(s=\"\",r=\"\",q=0;q<n;q+=3,r=\",\"){p=a[q]\no=a[q+1]?\"!\":\":\"\ns+=r+p+o+a[q+2].as}return s},\nfg(a,b,c){var s,r,q,p=b\nif(c.length>0)p+=\"<\"+A.ff(c)+\">\"\ns=a.eC.get(p)\nif(s!=null)return s\nr=new A.b1(null,null)\nr.w=9\nr.x=b\nr.y=c\nif(c.length>0)r.c=c[0]\nr.as=p\nq=A.bI(a,r)\na.eC.set(p,q)\nreturn q},\noZ(a,b,c){var s,r,q,p,o,n\nif(b.w===10){s=b.x\nr=b.y.concat(c)}else{r=c\ns=b}q=s.as+(\";<\"+A.ff(r)+\">\")\np=a.eC.get(q)\nif(p!=null)return p\no=new A.b1(null,null)\no.w=10\no.x=s\no.y=r\no.as=q\nn=A.bI(a,o)\na.eC.set(q,n)\nreturn n},\nqR(a,b,c){var s,r,q=\"+\"+(b+\"(\"+A.ff(c)+\")\"),p=a.eC.get(q)\nif(p!=null)return p\ns=new A.b1(null,null)\ns.w=11\ns.x=b\ns.y=c\ns.as=q\nr=A.bI(a,s)\na.eC.set(q,r)\nreturn r},\nqP(a,b,c){var s,r,q,p,o,n=b.as,m=c.a,l=m.length,k=c.b,j=k.length,i=c.c,h=i.length,g=\"(\"+A.ff(m)\nif(j>0){s=l>0?\",\":\"\"\ng+=s+\"[\"+A.ff(k)+\"]\"}if(h>0){s=l>0?\",\":\"\"\ng+=s+\"{\"+A.vd(i)+\"}\"}r=n+(g+\")\")\nq=a.eC.get(r)\nif(q!=null)return q\np=new A.b1(null,null)\np.w=12\np.x=b\np.y=c\np.as=r\no=A.bI(a,p)\na.eC.set(r,o)\nreturn o},\np_(a,b,c,d){var s,r=b.as+(\"<\"+A.ff(c)+\">\"),q=a.eC.get(r)\nif(q!=null)return q\ns=A.vf(a,b,c,r,d)\na.eC.set(r,s)\nreturn s},\nvf(a,b,c,d,e){var s,r,q,p,o,n,m,l\nif(e){s=c.length\nr=A.nG(s)\nfor(q=0,p=0;p<s;++p){o=c[p]\nif(o.w===1){r[p]=o;++q}}if(q>0){n=A.bN(a,b,r,0)\nm=A.dP(a,c,r,0)\nreturn A.p_(a,n,m,c!==m)}}l=new A.b1(null,null)\nl.w=13\nl.x=b\nl.y=c\nl.as=d\nreturn A.bI(a,l)},\nqJ(a,b,c,d){return{u:a,e:b,r:c,s:[],p:0,n:d}},\nqL(a){var s,r,q,p,o,n,m,l=a.r,k=a.s\nfor(s=l.length,r=0;r<s;){q=l.charCodeAt(r)\nif(q>=48&&q<=57)r=A.v4(r+1,q,l,k)\nelse if((((q|32)>>>0)-97&65535)<26||q===95||q===36||q===124)r=A.qK(a,r,l,k,!1)\nelse if(q===46)r=A.qK(a,r,l,k,!0)\nelse{++r\nswitch(q){case 44:break\ncase 58:k.push(!1)\nbreak\ncase 33:k.push(!0)\nbreak\ncase 59:k.push(A.cd(a.u,a.e,k.pop()))\nbreak\ncase 94:k.push(A.vi(a.u,k.pop()))\nbreak\ncase 35:k.push(A.fh(a.u,5,\"#\"))\nbreak\ncase 64:k.push(A.fh(a.u,2,\"@\"))\nbreak\ncase 126:k.push(A.fh(a.u,3,\"~\"))\nbreak\ncase 60:k.push(a.p)\na.p=k.length\nbreak\ncase 62:A.v6(a,k)\nbreak\ncase 38:A.v5(a,k)\nbreak\ncase 42:p=a.u\nk.push(A.qS(p,A.cd(p,a.e,k.pop()),a.n))\nbreak\ncase 63:p=a.u\nk.push(A.p0(p,A.cd(p,a.e,k.pop()),a.n))\nbreak\ncase 47:p=a.u\nk.push(A.qQ(p,A.cd(p,a.e,k.pop()),a.n))\nbreak\ncase 40:k.push(-3)\nk.push(a.p)\na.p=k.length\nbreak\ncase 41:A.v3(a,k)\nbreak\ncase 91:k.push(a.p)\na.p=k.length\nbreak\ncase 93:o=k.splice(a.p)\nA.qM(a.u,a.e,o)\na.p=k.pop()\nk.push(o)\nk.push(-1)\nbreak\ncase 123:k.push(a.p)\na.p=k.length\nbreak\ncase 125:o=k.splice(a.p)\nA.v8(a.u,a.e,o)\na.p=k.pop()\nk.push(o)\nk.push(-2)\nbreak\ncase 43:n=l.indexOf(\"(\",r)\nk.push(l.substring(r,n))\nk.push(-4)\nk.push(a.p)\na.p=k.length\nr=n+1\nbreak\ndefault:throw\"Bad character \"+q}}}m=k.pop()\nreturn A.cd(a.u,a.e,m)},\nv4(a,b,c,d){var s,r,q=b-48\nfor(s=c.length;a<s;++a){r=c.charCodeAt(a)\nif(!(r>=48&&r<=57))break\nq=q*10+(r-48)}d.push(q)\nreturn a},\nqK(a,b,c,d,e){var s,r,q,p,o,n,m=b+1\nfor(s=c.length;m<s;++m){r=c.charCodeAt(m)\nif(r===46){if(e)break\ne=!0}else{if(!((((r|32)>>>0)-97&65535)<26||r===95||r===36||r===124))q=r>=48&&r<=57\nelse q=!0\nif(!q)break}}p=c.substring(b,m)\nif(e){s=a.u\no=a.e\nif(o.w===10)o=o.x\nn=A.vm(s,o.x)[p]\nif(n==null)A.y('No \"'+p+'\" in \"'+A.uB(o)+'\"')\nd.push(A.fi(s,o,n))}else d.push(p)\nreturn m},\nv6(a,b){var s,r=a.u,q=A.qI(a,b),p=b.pop()\nif(typeof p==\"string\")b.push(A.fg(r,p,q))\nelse{s=A.cd(r,a.e,p)\nswitch(s.w){case 12:b.push(A.p_(r,s,q,a.n))\nbreak\ndefault:b.push(A.oZ(r,s,q))\nbreak}}},\nv3(a,b){var s,r,q,p=a.u,o=b.pop(),n=null,m=null\nif(typeof o==\"number\")switch(o){case-1:n=b.pop()\nbreak\ncase-2:m=b.pop()\nbreak\ndefault:b.push(o)\nbreak}else b.push(o)\ns=A.qI(a,b)\no=b.pop()\nswitch(o){case-3:o=b.pop()\nif(n==null)n=p.sEA\nif(m==null)m=p.sEA\nr=A.cd(p,a.e,o)\nq=new A.ig()\nq.a=s\nq.b=n\nq.c=m\nb.push(A.qP(p,r,q))\nreturn\ncase-4:b.push(A.qR(p,b.pop(),s))\nreturn\ndefault:throw A.a(A.e_(\"Unexpected state under `()`: \"+A.u(o)))}},\nv5(a,b){var s=b.pop()\nif(0===s){b.push(A.fh(a.u,1,\"0&\"))\nreturn}if(1===s){b.push(A.fh(a.u,4,\"1&\"))\nreturn}throw A.a(A.e_(\"Unexpected extended operation \"+A.u(s)))},\nqI(a,b){var s=b.splice(a.p)\nA.qM(a.u,a.e,s)\na.p=b.pop()\nreturn s},\ncd(a,b,c){if(typeof c==\"string\")return A.fg(a,c,a.sEA)\nelse if(typeof c==\"number\"){b.toString\nreturn A.v7(a,b,c)}else return c},\nqM(a,b,c){var s,r=c.length\nfor(s=0;s<r;++s)c[s]=A.cd(a,b,c[s])},\nv8(a,b,c){var s,r=c.length\nfor(s=2;s<r;s+=3)c[s]=A.cd(a,b,c[s])},\nv7(a,b,c){var s,r,q=b.w\nif(q===10){if(c===0)return b.x\ns=b.y\nr=s.length\nif(c<=r)return s[c-1]\nc-=r\nb=b.x\nq=b.w}else if(c===0)return b\nif(q!==9)throw A.a(A.e_(\"Indexed base must be an interface type\"))\ns=b.y\nif(c<=s.length)return s[c-1]\nthrow A.a(A.e_(\"Bad index \"+c+\" for \"+b.j(0)))},\nxd(a,b,c){var s,r=b.d\nif(r==null)r=b.d=new Map()\ns=r.get(c)\nif(s==null){s=A.a7(a,b,null,c,null,!1)?1:0\nr.set(c,s)}if(0===s)return!1\nif(1===s)return!0\nreturn!0},\na7(a,b,c,d,e,f){var s,r,q,p,o,n,m,l,k,j,i\nif(b===d)return!0\nif(!A.bP(d))s=d===t._\nelse s=!0\nif(s)return!0\nr=b.w\nif(r===4)return!0\nif(A.bP(b))return!1\ns=b.w\nif(s===1)return!0\nq=r===14\nif(q)if(A.a7(a,c[b.x],c,d,e,!1))return!0\np=d.w\ns=b===t.P||b===t.T\nif(s){if(p===8)return A.a7(a,b,c,d.x,e,!1)\nreturn d===t.P||d===t.T||p===7||p===6}if(d===t.K){if(r===8)return A.a7(a,b.x,c,d,e,!1)\nif(r===6)return A.a7(a,b.x,c,d,e,!1)\nreturn r!==7}if(r===6)return A.a7(a,b.x,c,d,e,!1)\nif(p===6){s=A.qc(a,d)\nreturn A.a7(a,b,c,s,e,!1)}if(r===8){if(!A.a7(a,b.x,c,d,e,!1))return!1\nreturn A.a7(a,A.oE(a,b),c,d,e,!1)}if(r===7){s=A.a7(a,t.P,c,d,e,!1)\nreturn s&&A.a7(a,b.x,c,d,e,!1)}if(p===8){if(A.a7(a,b,c,d.x,e,!1))return!0\nreturn A.a7(a,b,c,A.oE(a,d),e,!1)}if(p===7){s=A.a7(a,b,c,t.P,e,!1)\nreturn s||A.a7(a,b,c,d.x,e,!1)}if(q)return!1\ns=r!==12\nif((!s||r===13)&&d===t.b8)return!0\no=r===11\nif(o&&d===t.fl)return!0\nif(p===13){if(b===t.g)return!0\nif(r!==13)return!1\nn=b.y\nm=d.y\nl=n.length\nif(l!==m.length)return!1\nc=c==null?n:n.concat(c)\ne=e==null?m:m.concat(e)\nfor(k=0;k<l;++k){j=n[k]\ni=m[k]\nif(!A.a7(a,j,c,i,e,!1)||!A.a7(a,i,e,j,c,!1))return!1}return A.rg(a,b.x,c,d.x,e,!1)}if(p===12){if(b===t.g)return!0\nif(s)return!1\nreturn A.rg(a,b,c,d,e,!1)}if(r===9){if(p!==9)return!1\nreturn A.w1(a,b,c,d,e,!1)}if(o&&p===11)return A.w5(a,b,c,d,e,!1)\nreturn!1},\nrg(a3,a4,a5,a6,a7,a8){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1,a2\nif(!A.a7(a3,a4.x,a5,a6.x,a7,!1))return!1\ns=a4.y\nr=a6.y\nq=s.a\np=r.a\no=q.length\nn=p.length\nif(o>n)return!1\nm=n-o\nl=s.b\nk=r.b\nj=l.length\ni=k.length\nif(o+j<n+i)return!1\nfor(h=0;h<o;++h){g=q[h]\nif(!A.a7(a3,p[h],a7,g,a5,!1))return!1}for(h=0;h<m;++h){g=l[h]\nif(!A.a7(a3,p[o+h],a7,g,a5,!1))return!1}for(h=0;h<i;++h){g=l[m+h]\nif(!A.a7(a3,k[h],a7,g,a5,!1))return!1}f=s.c\ne=r.c\nd=f.length\nc=e.length\nfor(b=0,a=0;a<c;a+=3){a0=e[a]\nfor(;!0;){if(b>=d)return!1\na1=f[b]\nb+=3\nif(a0<a1)return!1\na2=f[b-2]\nif(a1<a0){if(a2)return!1\ncontinue}g=e[a+1]\nif(a2&&!g)return!1\ng=f[b-1]\nif(!A.a7(a3,e[a+2],a7,g,a5,!1))return!1\nbreak}}for(;b<d;){if(f[b+1])return!1\nb+=3}return!0},\nw1(a,b,c,d,e,f){var s,r,q,p,o,n=b.x,m=d.x\nfor(;n!==m;){s=a.tR[n]\nif(s==null)return!1\nif(typeof s==\"string\"){n=s\ncontinue}r=s[m]\nif(r==null)return!1\nq=r.length\np=q>0?new Array(q):v.typeUniverse.sEA\nfor(o=0;o<q;++o)p[o]=A.fi(a,b,r[o])\nreturn A.r7(a,p,null,c,d.y,e,!1)}return A.r7(a,b.y,null,c,d.y,e,!1)},\nr7(a,b,c,d,e,f,g){var s,r=b.length\nfor(s=0;s<r;++s)if(!A.a7(a,b[s],d,e[s],f,!1))return!1\nreturn!0},\nw5(a,b,c,d,e,f){var s,r=b.y,q=d.y,p=r.length\nif(p!==q.length)return!1\nif(b.x!==d.x)return!1\nfor(s=0;s<p;++s)if(!A.a7(a,r[s],c,q[s],e,!1))return!1\nreturn!0},\nft(a){var s=a.w,r=!0\nif(!(a===t.P||a===t.T))if(!A.bP(a))if(s!==7)if(!(s===6&&A.ft(a.x)))r=s===8&&A.ft(a.x)\nreturn r},\nxc(a){var s\nif(!A.bP(a))s=a===t._\nelse s=!0\nreturn s},\nbP(a){var s=a.w\nreturn s===2||s===3||s===4||s===5||a===t.X},\nr6(a,b){var s,r,q=Object.keys(b),p=q.length\nfor(s=0;s<p;++s){r=q[s]\na[r]=b[r]}},\nnG(a){return a>0?new Array(a):v.typeUniverse.sEA},\nb1:function b1(a,b){var _=this\n_.a=a\n_.b=b\n_.r=_.f=_.d=_.c=null\n_.w=0\n_.as=_.Q=_.z=_.y=_.x=null},\nig:function ig(){this.c=this.b=this.a=null},\nny:function ny(a){this.a=a},\nib:function ib(){},\nfe:function fe(a){this.a=a},\nuQ(){var s,r,q={}\nif(self.scheduleImmediate!=null)return A.wy()\nif(self.MutationObserver!=null&&self.document!=null){s=self.document.createElement(\"div\")\nr=self.document.createElement(\"span\")\nq.a=null\nnew self.MutationObserver(A.cf(new A.lQ(q),1)).observe(s,{childList:true})\nreturn new A.lP(q,s,r)}else if(self.setImmediate!=null)return A.wz()\nreturn A.wA()},\nuR(a){self.scheduleImmediate(A.cf(new A.lR(a),0))},\nuS(a){self.setImmediate(A.cf(new A.lS(a),0))},\nuT(a){A.oK(B.z,a)},\noK(a,b){var s=B.b.I(a.a,1000)\nreturn A.va(s<0?0:s,b)},\nva(a,b){var s=new A.iD()\ns.hR(a,b)\nreturn s},\nvb(a,b){var s=new A.iD()\ns.hS(a,b)\nreturn s},\no(a){return new A.i_(new A.k($.i,a.h(\"k<0>\")),a.h(\"i_<0>\"))},\nn(a,b){a.$2(0,null)\nb.b=!0\nreturn b.a},\nc(a,b){A.vE(a,b)},\nm(a,b){b.L(a)},\nl(a,b){b.bx(A.E(a),A.R(a))},\nvE(a,b){var s,r,q=new A.nI(b),p=new A.nJ(b)\nif(a instanceof A.k)a.fN(q,p,t.z)\nelse{s=t.z\nif(a instanceof A.k)a.bG(q,p,s)\nelse{r=new A.k($.i,t.eI)\nr.a=8\nr.c=a\nr.fN(q,p,s)}}},\np(a){var s=function(b,c){return function(d,e){while(true){try{b(d,e)\nbreak}catch(r){e=r\nd=c}}}}(a,1)\nreturn $.i.d5(new A.nZ(s),t.H,t.S,t.z)},\nqO(a,b,c){return 0},\niV(a,b){var s=A.aD(a,\"error\",t.K)\nreturn new A.cS(s,b==null?A.fD(a):b)},\nfD(a){var s\nif(t.w.b(a)){s=a.gbJ()\nif(s!=null)return s}return B.bu},\nu8(a,b){var s=new A.k($.i,b.h(\"k<0>\"))\nA.qi(B.z,new A.jX(a,s))\nreturn s},\njW(a,b){var s,r,q,p,o,n,m=null\ntry{m=a.$0()}catch(o){s=A.E(o)\nr=A.R(o)\nn=$.i\nq=new A.k(n,b.h(\"k<0>\"))\np=n.aL(s,r)\nif(p!=null)q.aE(p.a,p.b)\nelse q.aE(s,r)\nreturn q}return b.h(\"C<0>\").b(m)?m:A.eX(m,b)},\naX(a,b){var s=a==null?b.a(a):a,r=new A.k($.i,b.h(\"k<0>\"))\nr.b1(s)\nreturn r},\npQ(a,b,c){var s,r\nA.aD(a,\"error\",t.K)\ns=$.i\nif(s!==B.d){r=s.aL(a,b)\nif(r!=null){a=r.a\nb=r.b}}if(b==null)b=A.fD(a)\ns=new A.k($.i,c.h(\"k<0>\"))\ns.aE(a,b)\nreturn s},\npP(a,b){var s,r=!b.b(null)\nif(r)throw A.a(A.ag(null,\"computation\",\"The type parameter is not nullable\"))\ns=new A.k($.i,b.h(\"k<0>\"))\nA.qi(a,new A.jV(null,s,b))\nreturn s},\nou(a,b){var s,r,q,p,o,n,m,l,k={},j=null,i=!1,h=new A.k($.i,b.h(\"k<q<0>>\"))\nk.a=null\nk.b=0\nk.c=k.d=null\ns=new A.jZ(k,j,i,h)\ntry{for(n=J.M(a),m=t.P;n.k();){r=n.gm()\nq=k.b\nr.bG(new A.jY(k,q,h,b,j,i),s,m);++k.b}n=k.b\nif(n===0){n=h\nn.bq(A.d([],b.h(\"w<0>\")))\nreturn n}k.a=A.b_(n,null,!1,b.h(\"0?\"))}catch(l){p=A.E(l)\no=A.R(l)\nif(k.b===0||i)return A.pQ(p,o,b.h(\"q<0>\"))\nelse{k.d=p\nk.c=o}}return h},\np6(a,b,c){var s=$.i.aL(b,c)\nif(s!=null){b=s.a\nc=s.b}else if(c==null)c=A.fD(b)\na.W(b,c)},\nv0(a,b,c){var s=new A.k(b,c.h(\"k<0>\"))\ns.a=8\ns.c=a\nreturn s},\neX(a,b){var s=new A.k($.i,b.h(\"k<0>\"))\ns.a=8\ns.c=a\nreturn s},\noV(a,b){var s,r\nfor(;s=a.a,(s&4)!==0;)a=a.c\nif(a===b){b.aE(new A.aV(!0,a,null,\"Cannot complete a future with itself\"),A.oG())\nreturn}s|=b.a&1\na.a=s\nif((s&24)!==0){r=b.cE()\nb.cu(a)\nA.du(b,r)}else{r=b.c\nb.fH(a)\na.dY(r)}},\nv1(a,b){var s,r,q={},p=q.a=a\nfor(;s=p.a,(s&4)!==0;){p=p.c\nq.a=p}if(p===b){b.aE(new A.aV(!0,p,null,\"Cannot complete a future with itself\"),A.oG())\nreturn}if((s&24)===0){r=b.c\nb.fH(p)\nq.a.dY(r)\nreturn}if((s&16)===0&&b.c==null){b.cu(p)\nreturn}b.a^=2\nb.b.b_(new A.mm(q,b))},\ndu(a,b){var s,r,q,p,o,n,m,l,k,j,i,h,g={},f=g.a=a\nfor(;!0;){s={}\nr=f.a\nq=(r&16)===0\np=!q\nif(b==null){if(p&&(r&1)===0){r=f.c\nf.b.c4(r.a,r.b)}return}s.a=b\no=b.a\nfor(f=b;o!=null;f=o,o=n){f.a=null\nA.du(g.a,f)\ns.a=o\nn=o.a}r=g.a\nm=r.c\ns.b=p\ns.c=m\nif(q){l=f.c\nl=(l&1)!==0||(l&15)===8}else l=!0\nif(l){k=f.b.b\nif(p){f=r.b\nf=!(f===k||f.gbb()===k.gbb())}else f=!1\nif(f){f=g.a\nr=f.c\nf.b.c4(r.a,r.b)\nreturn}j=$.i\nif(j!==k)$.i=k\nelse j=null\nf=s.a.c\nif((f&15)===8)new A.mt(s,g,p).$0()\nelse if(q){if((f&1)!==0)new A.ms(s,m).$0()}else if((f&2)!==0)new A.mr(g,s).$0()\nif(j!=null)$.i=j\nf=s.c\nif(f instanceof A.k){r=s.a.$ti\nr=r.h(\"C<2>\").b(f)||!r.y[1].b(f)}else r=!1\nif(r){i=s.a.b\nif((f.a&24)!==0){h=i.c\ni.c=null\nb=i.cF(h)\ni.a=f.a&30|i.a&1\ni.c=f.c\ng.a=f\ncontinue}else A.oV(f,i)\nreturn}}i=s.a.b\nh=i.c\ni.c=null\nb=i.cF(h)\nf=s.b\nr=s.c\nif(!f){i.a=8\ni.c=r}else{i.a=i.a&1|16\ni.c=r}g.a=i\nf=i}},\nwi(a,b){if(t.b.b(a))return b.d5(a,t.z,t.K,t.l)\nif(t.bI.b(a))return b.be(a,t.z,t.K)\nthrow A.a(A.ag(a,\"onError\",u.c))},\nwa(){var s,r\nfor(s=$.dO;s!=null;s=$.dO){$.fp=null\nr=s.b\n$.dO=r\nif(r==null)$.fo=null\ns.a.$0()}},\nwr(){$.p9=!0\ntry{A.wa()}finally{$.fp=null\n$.p9=!1\nif($.dO!=null)$.pt().$1(A.rw())}},\nrq(a){var s=new A.i0(a),r=$.fo\nif(r==null){$.dO=$.fo=s\nif(!$.p9)$.pt().$1(A.rw())}else $.fo=r.b=s},\nwq(a){var s,r,q,p=$.dO\nif(p==null){A.rq(a)\n$.fp=$.fo\nreturn}s=new A.i0(a)\nr=$.fp\nif(r==null){s.b=p\n$.dO=$.fp=s}else{q=r.b\ns.b=q\n$.fp=r.b=s\nif(q==null)$.fo=s}},\noh(a){var s,r=null,q=$.i\nif(B.d===q){A.nW(r,r,B.d,a)\nreturn}if(B.d===q.ge1().a)s=B.d.gbb()===q.gbb()\nelse s=!1\nif(s){A.nW(r,r,q,q.au(a,t.H))\nreturn}s=$.i\ns.b_(s.cQ(a))},\nxS(a){return new A.dG(A.aD(a,\"stream\",t.K))},\neD(a,b,c,d){var s=null\nreturn c?new A.dK(b,s,s,a,d.h(\"dK<0>\")):new A.dn(b,s,s,a,d.h(\"dn<0>\"))},\niM(a){var s,r,q\nif(a==null)return\ntry{a.$0()}catch(q){s=A.E(q)\nr=A.R(q)\n$.i.c4(s,r)}},\nv_(a,b,c,d,e,f){var s=$.i,r=e?1:0,q=c!=null?32:0,p=A.i5(s,b,f),o=A.i6(s,c),n=d==null?A.rv():d\nreturn new A.cb(a,p,o,s.au(n,t.H),s,r|q,f.h(\"cb<0>\"))},\ni5(a,b,c){var s=b==null?A.wB():b\nreturn a.be(s,t.H,c)},\ni6(a,b){if(b==null)b=A.wC()\nif(t.da.b(b))return a.d5(b,t.z,t.K,t.l)\nif(t.d5.b(b))return a.be(b,t.z,t.K)\nthrow A.a(A.K(\"handleError callback must take either an Object (the error), or both an Object (the error) and a StackTrace.\",null))},\nwb(a){},\nwd(a,b){$.i.c4(a,b)},\nwc(){},\nwo(a,b,c){var s,r,q,p,o,n\ntry{b.$1(a.$0())}catch(n){s=A.E(n)\nr=A.R(n)\nq=$.i.aL(s,r)\nif(q==null)c.$2(s,r)\nelse{p=q.a\no=q.b\nc.$2(p,o)}}},\nvK(a,b,c,d){var s=a.J(),r=$.ci()\nif(s!==r)s.ai(new A.nL(b,c,d))\nelse b.W(c,d)},\nvL(a,b){return new A.nK(a,b)},\nr8(a,b,c){var s=a.J(),r=$.ci()\nif(s!==r)s.ai(new A.nM(b,c))\nelse b.b2(c)},\nv9(a,b,c){return new A.dE(new A.nr(null,null,a,c,b),b.h(\"@<0>\").H(c).h(\"dE<1,2>\"))},\nqi(a,b){var s=$.i\nif(s===B.d)return s.ei(a,b)\nreturn s.ei(a,s.cQ(b))},\nwm(a,b,c,d,e){A.fq(d,e)},\nfq(a,b){A.wq(new A.nS(a,b))},\nnT(a,b,c,d){var s,r=$.i\nif(r===c)return d.$0()\n$.i=c\ns=r\ntry{r=d.$0()\nreturn r}finally{$.i=s}},\nnV(a,b,c,d,e){var s,r=$.i\nif(r===c)return d.$1(e)\n$.i=c\ns=r\ntry{r=d.$1(e)\nreturn r}finally{$.i=s}},\nnU(a,b,c,d,e,f){var s,r=$.i\nif(r===c)return d.$2(e,f)\n$.i=c\ns=r\ntry{r=d.$2(e,f)\nreturn r}finally{$.i=s}},\nrm(a,b,c,d){return d},\nrn(a,b,c,d){return d},\nrl(a,b,c,d){return d},\nwl(a,b,c,d,e){return null},\nnW(a,b,c,d){var s,r\nif(B.d!==c){s=B.d.gbb()\nr=c.gbb()\nd=s!==r?c.cQ(d):c.ef(d,t.H)}A.rq(d)},\nwk(a,b,c,d,e){return A.oK(d,B.d!==c?c.ef(e,t.H):e)},\nwj(a,b,c,d,e){var s\nif(B.d!==c)e=c.fU(e,t.H,t.aF)\ns=B.b.I(d.a,1000)\nreturn A.vb(s<0?0:s,e)},\nwn(a,b,c,d){A.pn(d)},\nwf(a){$.i.hf(a)},\nrk(a,b,c,d,e){var s,r,q\n$.rK=A.wD()\nif(d==null)d=B.bI\nif(e==null)s=c.gfm()\nelse{r=t.X\ns=A.u9(e,r,r)}r=new A.i7(c.gfE(),c.gfG(),c.gfF(),c.gfA(),c.gfB(),c.gfz(),c.gfd(),c.ge1(),c.gfa(),c.gf9(),c.gft(),c.gfg(),c.gdS(),c,s)\nq=d.a\nif(q!=null)r.as=new A.au(r,q)\nreturn r},\nxs(a,b,c){A.aD(a,\"body\",c.h(\"0()\"))\nreturn A.wp(a,b,null,c)},\nwp(a,b,c,d){return $.i.h4(c,b).bg(a,d)},\nlQ:function lQ(a){this.a=a},\nlP:function lP(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nlR:function lR(a){this.a=a},\nlS:function lS(a){this.a=a},\niD:function iD(){this.c=0},\nnx:function nx(a,b){this.a=a\nthis.b=b},\nnw:function nw(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\ni_:function i_(a,b){this.a=a\nthis.b=!1\nthis.$ti=b},\nnI:function nI(a){this.a=a},\nnJ:function nJ(a){this.a=a},\nnZ:function nZ(a){this.a=a},\niB:function iB(a){var _=this\n_.a=a\n_.e=_.d=_.c=_.b=null},\ndJ:function dJ(a,b){this.a=a\nthis.$ti=b},\ncS:function cS(a,b){this.a=a\nthis.b=b},\neM:function eM(a,b){this.a=a\nthis.$ti=b},\ncB:function cB(a,b,c,d,e,f,g){var _=this\n_.ay=0\n_.CW=_.ch=null\n_.w=a\n_.a=b\n_.b=c\n_.c=d\n_.d=e\n_.e=f\n_.r=_.f=null\n_.$ti=g},\ncA:function cA(){},\nfd:function fd(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=0\n_.r=_.f=_.e=_.d=null\n_.$ti=c},\nnt:function nt(a,b){this.a=a\nthis.b=b},\nnv:function nv(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nnu:function nu(a){this.a=a},\njX:function jX(a,b){this.a=a\nthis.b=b},\njV:function jV(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\njZ:function jZ(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\njY:function jY(a,b,c,d,e,f){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f},\ndp:function dp(){},\na2:function a2(a,b){this.a=a\nthis.$ti=b},\na8:function a8(a,b){this.a=a\nthis.$ti=b},\ncc:function cc(a,b,c,d,e){var _=this\n_.a=null\n_.b=a\n_.c=b\n_.d=c\n_.e=d\n_.$ti=e},\nk:function k(a,b){var _=this\n_.a=0\n_.b=a\n_.c=null\n_.$ti=b},\nmj:function mj(a,b){this.a=a\nthis.b=b},\nmq:function mq(a,b){this.a=a\nthis.b=b},\nmn:function mn(a){this.a=a},\nmo:function mo(a){this.a=a},\nmp:function mp(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nmm:function mm(a,b){this.a=a\nthis.b=b},\nml:function ml(a,b){this.a=a\nthis.b=b},\nmk:function mk(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nmt:function mt(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nmu:function mu(a){this.a=a},\nms:function ms(a,b){this.a=a\nthis.b=b},\nmr:function mr(a,b){this.a=a\nthis.b=b},\ni0:function i0(a){this.a=a\nthis.b=null},\nY:function Y(){},\nl_:function l_(a,b){this.a=a\nthis.b=b},\nl0:function l0(a,b){this.a=a\nthis.b=b},\nkY:function kY(a){this.a=a},\nkZ:function kZ(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nkW:function kW(a,b){this.a=a\nthis.b=b},\nkX:function kX(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\nkU:function kU(a,b){this.a=a\nthis.b=b},\nkV:function kV(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nhD:function hD(){},\ncI:function cI(){},\nnq:function nq(a){this.a=a},\nnp:function np(a){this.a=a},\niC:function iC(){},\ni1:function i1(){},\ndn:function dn(a,b,c,d,e){var _=this\n_.a=null\n_.b=0\n_.c=null\n_.d=a\n_.e=b\n_.f=c\n_.r=d\n_.$ti=e},\ndK:function dK(a,b,c,d,e){var _=this\n_.a=null\n_.b=0\n_.c=null\n_.d=a\n_.e=b\n_.f=c\n_.r=d\n_.$ti=e},\nan:function an(a,b){this.a=a\nthis.$ti=b},\ncb:function cb(a,b,c,d,e,f,g){var _=this\n_.w=a\n_.a=b\n_.b=c\n_.c=d\n_.d=e\n_.e=f\n_.r=_.f=null\n_.$ti=g},\ndH:function dH(a){this.a=a},\naf:function af(){},\nm2:function m2(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nm1:function m1(a){this.a=a},\ndF:function dF(){},\nia:function ia(){},\ndq:function dq(a){this.b=a\nthis.a=null},\neQ:function eQ(a,b){this.b=a\nthis.c=b\nthis.a=null},\nmc:function mc(){},\nf5:function f5(){this.a=0\nthis.c=this.b=null},\nnf:function nf(a,b){this.a=a\nthis.b=b},\neR:function eR(a){this.a=1\nthis.b=a\nthis.c=null},\ndG:function dG(a){this.a=null\nthis.b=a\nthis.c=!1},\nnL:function nL(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nnK:function nK(a,b){this.a=a\nthis.b=b},\nnM:function nM(a,b){this.a=a\nthis.b=b},\neW:function eW(){},\nds:function ds(a,b,c,d,e,f,g){var _=this\n_.w=a\n_.x=null\n_.a=b\n_.b=c\n_.c=d\n_.d=e\n_.e=f\n_.r=_.f=null\n_.$ti=g},\nf0:function f0(a,b,c){this.b=a\nthis.a=b\nthis.$ti=c},\neT:function eT(a){this.a=a},\ndD:function dD(a,b,c,d,e,f){var _=this\n_.w=$\n_.x=null\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.r=_.f=null\n_.$ti=f},\nfc:function fc(){},\neL:function eL(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\ndv:function dv(a,b,c,d,e){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.$ti=e},\ndE:function dE(a,b){this.a=a\nthis.$ti=b},\nnr:function nr(a,b,c,d,e){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e},\nau:function au(a,b){this.a=a\nthis.b=b},\niI:function iI(a,b,c,d,e,f,g,h,i,j,k,l,m){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f\n_.r=g\n_.w=h\n_.x=i\n_.y=j\n_.z=k\n_.Q=l\n_.as=m},\ndM:function dM(a){this.a=a},\niH:function iH(){},\ni7:function i7(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f\n_.r=g\n_.w=h\n_.x=i\n_.y=j\n_.z=k\n_.Q=l\n_.as=m\n_.at=null\n_.ax=n\n_.ay=o},\nm9:function m9(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nmb:function mb(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\nm8:function m8(a,b){this.a=a\nthis.b=b},\nma:function ma(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nnS:function nS(a,b){this.a=a\nthis.b=b},\niw:function iw(){},\nnk:function nk(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nnm:function nm(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\nnj:function nj(a,b){this.a=a\nthis.b=b},\nnl:function nl(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\npS(a,b){return new A.cE(a.h(\"@<0>\").H(b).h(\"cE<1,2>\"))},\nqH(a,b){var s=a[b]\nreturn s===a?null:s},\noX(a,b,c){if(c==null)a[b]=a\nelse a[b]=c},\noW(){var s=Object.create(null)\nA.oX(s,\"<non-identifier-key>\",s)\ndelete s[\"<non-identifier-key>\"]\nreturn s},\nuh(a,b){return new A.bu(a.h(\"@<0>\").H(b).h(\"bu<1,2>\"))},\nkf(a,b,c){return A.x_(a,new A.bu(b.h(\"@<0>\").H(c).h(\"bu<1,2>\")))},\na3(a,b){return new A.bu(a.h(\"@<0>\").H(b).h(\"bu<1,2>\"))},\noC(a){return new A.eZ(a.h(\"eZ<0>\"))},\noY(){var s=Object.create(null)\ns[\"<non-identifier-key>\"]=s\ndelete s[\"<non-identifier-key>\"]\nreturn s},\nim(a,b,c){var s=new A.dy(a,b,c.h(\"dy<0>\"))\ns.c=a.e\nreturn s},\nu9(a,b,c){var s=A.pS(b,c)\na.aa(0,new A.k1(s,b,c))\nreturn s},\noD(a){var s,r={}\nif(A.pk(a))return\"{...}\"\ns=new A.av(\"\")\ntry{$.cO.push(a)\ns.a+=\"{\"\nr.a=!0\na.aa(0,new A.kj(r,s))\ns.a+=\"}\"}finally{$.cO.pop()}r=s.a\nreturn r.charCodeAt(0)==0?r:r},\ncE:function cE(a){var _=this\n_.a=0\n_.e=_.d=_.c=_.b=null\n_.$ti=a},\nmv:function mv(a){this.a=a},\ndw:function dw(a){var _=this\n_.a=0\n_.e=_.d=_.c=_.b=null\n_.$ti=a},\ncF:function cF(a,b){this.a=a\nthis.$ti=b},\nih:function ih(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=0\n_.d=null\n_.$ti=c},\neZ:function eZ(a){var _=this\n_.a=0\n_.f=_.e=_.d=_.c=_.b=null\n_.r=0\n_.$ti=a},\nne:function ne(a){this.a=a\nthis.c=this.b=null},\ndy:function dy(a,b,c){var _=this\n_.a=a\n_.b=b\n_.d=_.c=null\n_.$ti=c},\nk1:function k1(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nem:function em(a){var _=this\n_.b=_.a=0\n_.c=null\n_.$ti=a},\nio:function io(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=null\n_.d=c\n_.e=!1\n_.$ti=d},\naF:function aF(){},\nz:function z(){},\nT:function T(){},\nki:function ki(a){this.a=a},\nkj:function kj(a,b){this.a=a\nthis.b=b},\nf_:function f_(a,b){this.a=a\nthis.$ti=b},\nip:function ip(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=null\n_.$ti=c},\ndd:function dd(){},\nf8:function f8(){},\nvz(a,b,c){var s,r,q,p,o=c-b\nif(o<=4096)s=$.tc()\nelse s=new Uint8Array(o)\nfor(r=J.V(a),q=0;q<o;++q){p=r.i(a,b+q)\nif((p&255)!==p)p=255\ns[q]=p}return s},\nvy(a,b,c,d){var s=a?$.tb():$.ta()\nif(s==null)return null\nif(0===c&&d===b.length)return A.r5(s,b)\nreturn A.r5(s,b.subarray(c,d))},\nr5(a,b){var s,r\ntry{s=a.decode(b)\nreturn s}catch(r){}return null},\npA(a,b,c,d,e,f){if(B.b.aA(f,4)!==0)throw A.a(A.ai(\"Invalid base64 padding, padded length must be multiple of four, is \"+f,a,c))\nif(d+e!==f)throw A.a(A.ai(\"Invalid base64 padding, '=' not at the end\",a,b))\nif(e>2)throw A.a(A.ai(\"Invalid base64 padding, more than two '=' characters\",a,b))},\nvA(a){switch(a){case 65:return\"Missing extension byte\"\ncase 67:return\"Unexpected extension byte\"\ncase 69:return\"Invalid UTF-8 byte\"\ncase 71:return\"Overlong encoding\"\ncase 73:return\"Out of unicode range\"\ncase 75:return\"Encoded surrogate\"\ncase 77:return\"Unfinished UTF-8 octet sequence\"\ndefault:return\"\"}},\nnE:function nE(){},\nnD:function nD(){},\nfA:function fA(){},\niF:function iF(){},\nfB:function fB(a){this.a=a},\nfF:function fF(){},\nfG:function fG(){},\ncm:function cm(){},\ncn:function cn(){},\nfW:function fW(){},\nhO:function hO(){},\nhP:function hP(){},\nnF:function nF(a){this.b=this.a=0\nthis.c=a},\nfm:function fm(a){this.a=a\nthis.b=16\nthis.c=0},\npC(a){var s=A.qF(a,null)\nif(s==null)A.y(A.ai(\"Could not parse BigInt\",a,null))\nreturn s},\noU(a,b){var s=A.qF(a,b)\nif(s==null)throw A.a(A.ai(\"Could not parse BigInt\",a,null))\nreturn s},\nuX(a,b){var s,r,q=$.b7(),p=a.length,o=4-p%4\nif(o===4)o=0\nfor(s=0,r=0;r<p;++r){s=s*10+a.charCodeAt(r)-48;++o\nif(o===4){q=q.bI(0,$.pu()).dh(0,A.eJ(s))\ns=0\no=0}}if(b)return q.aB(0)\nreturn q},\nqx(a){if(48<=a&&a<=57)return a-48\nreturn(a|32)-97+10},\nuY(a,b,c){var s,r,q,p,o,n,m,l=a.length,k=l-b,j=B.aH.jE(k/4),i=new Uint16Array(j),h=j-1,g=k-h*4\nfor(s=b,r=0,q=0;q<g;++q,s=p){p=s+1\no=A.qx(a.charCodeAt(s))\nif(o>=16)return null\nr=r*16+o}n=h-1\ni[h]=r\nfor(;s<l;n=m){for(r=0,q=0;q<4;++q,s=p){p=s+1\no=A.qx(a.charCodeAt(s))\nif(o>=16)return null\nr=r*16+o}m=n-1\ni[n]=r}if(j===1&&i[0]===0)return $.b7()\nl=A.aJ(j,i)\nreturn new A.a6(l===0?!1:c,i,l)},\nqF(a,b){var s,r,q,p,o\nif(a===\"\")return null\ns=$.t5().a9(a)\nif(s==null)return null\nr=s.b\nq=r[1]===\"-\"\np=r[4]\no=r[3]\nif(p!=null)return A.uX(p,q)\nif(o!=null)return A.uY(o,2,q)\nreturn null},\naJ(a,b){while(!0){if(!(a>0&&b[a-1]===0))break;--a}return a},\noS(a,b,c,d){var s,r=new Uint16Array(d),q=c-b\nfor(s=0;s<q;++s)r[s]=a[b+s]\nreturn r},\nqw(a){var s\nif(a===0)return $.b7()\nif(a===1)return $.fv()\nif(a===2)return $.t6()\nif(Math.abs(a)<4294967296)return A.eJ(B.b.kE(a))\ns=A.uU(a)\nreturn s},\neJ(a){var s,r,q,p,o=a<0\nif(o){if(a===-9223372036854776e3){s=new Uint16Array(4)\ns[3]=32768\nr=A.aJ(4,s)\nreturn new A.a6(r!==0,s,r)}a=-a}if(a<65536){s=new Uint16Array(1)\ns[0]=a\nr=A.aJ(1,s)\nreturn new A.a6(r===0?!1:o,s,r)}if(a<=4294967295){s=new Uint16Array(2)\ns[0]=a&65535\ns[1]=B.b.P(a,16)\nr=A.aJ(2,s)\nreturn new A.a6(r===0?!1:o,s,r)}r=B.b.I(B.b.gfV(a)-1,16)+1\ns=new Uint16Array(r)\nfor(q=0;a!==0;q=p){p=q+1\ns[q]=a&65535\na=B.b.I(a,65536)}r=A.aJ(r,s)\nreturn new A.a6(r===0?!1:o,s,r)},\nuU(a){var s,r,q,p,o,n,m,l,k\nif(isNaN(a)||a==1/0||a==-1/0)throw A.a(A.K(\"Value must be finite: \"+a,null))\ns=a<0\nif(s)a=-a\na=Math.floor(a)\nif(a===0)return $.b7()\nr=$.t4()\nfor(q=0;q<8;++q)r[q]=0\nA.q_(r.buffer,0,null).setFloat64(0,a,!0)\np=r[7]\no=r[6]\nn=(p<<4>>>0)+(o>>>4)-1075\nm=new Uint16Array(4)\nm[0]=(r[1]<<8>>>0)+r[0]\nm[1]=(r[3]<<8>>>0)+r[2]\nm[2]=(r[5]<<8>>>0)+r[4]\nm[3]=o&15|16\nl=new A.a6(!1,m,4)\nif(n<0)k=l.bl(0,-n)\nelse k=n>0?l.b0(0,n):l\nif(s)return k.aB(0)\nreturn k},\noT(a,b,c,d){var s\nif(b===0)return 0\nif(c===0&&d===a)return b\nfor(s=b-1;s>=0;--s)d[s+c]=a[s]\nfor(s=c-1;s>=0;--s)d[s]=0\nreturn b+c},\nqD(a,b,c,d){var s,r,q,p=B.b.I(c,16),o=B.b.aA(c,16),n=16-o,m=B.b.b0(1,n)-1\nfor(s=b-1,r=0;s>=0;--s){q=a[s]\nd[s+p+1]=(B.b.bl(q,n)|r)>>>0\nr=B.b.b0((q&m)>>>0,o)}d[p]=r},\nqy(a,b,c,d){var s,r,q,p=B.b.I(c,16)\nif(B.b.aA(c,16)===0)return A.oT(a,b,p,d)\ns=b+p+1\nA.qD(a,b,c,d)\nfor(r=p;--r,r>=0;)d[r]=0\nq=s-1\nreturn d[q]===0?q:s},\nuZ(a,b,c,d){var s,r,q=B.b.I(c,16),p=B.b.aA(c,16),o=16-p,n=B.b.b0(1,p)-1,m=B.b.bl(a[q],p),l=b-q-1\nfor(s=0;s<l;++s){r=a[s+q+1]\nd[s]=(B.b.b0((r&n)>>>0,o)|m)>>>0\nm=B.b.bl(r,p)}d[l]=m},\nlZ(a,b,c,d){var s,r=b-d\nif(r===0)for(s=b-1;s>=0;--s){r=a[s]-c[s]\nif(r!==0)return r}return r},\nuV(a,b,c,d,e){var s,r\nfor(s=0,r=0;r<d;++r){s+=a[r]+c[r]\ne[r]=s&65535\ns=B.b.P(s,16)}for(r=d;r<b;++r){s+=a[r]\ne[r]=s&65535\ns=B.b.P(s,16)}e[b]=s},\ni4(a,b,c,d,e){var s,r\nfor(s=0,r=0;r<d;++r){s+=a[r]-c[r]\ne[r]=s&65535\ns=0-(B.b.P(s,16)&1)}for(r=d;r<b;++r){s+=a[r]\ne[r]=s&65535\ns=0-(B.b.P(s,16)&1)}},\nqE(a,b,c,d,e,f){var s,r,q,p,o\nif(a===0)return\nfor(s=0;--f,f>=0;e=p,c=r){r=c+1\nq=a*b[c]+d[e]+s\np=e+1\nd[e]=q&65535\ns=B.b.I(q,65536)}for(;s!==0;e=p){o=d[e]+s\np=e+1\nd[e]=o&65535\ns=B.b.I(o,65536)}},\nuW(a,b,c){var s,r=b[c]\nif(r===a)return 65535\ns=B.b.eX((r<<16|b[c-1])>>>0,a)\nif(s>65535)return 65535\nreturn s},\nu_(a){throw A.a(A.ag(a,\"object\",\"Expandos are not allowed on strings, numbers, bools, records or null\"))},\naN(a,b){var s=A.q4(a,b)\nif(s!=null)return s\nthrow A.a(A.ai(a,null,null))},\ntZ(a,b){a=A.a(a)\na.stack=b.j(0)\nthrow a\nthrow A.a(\"unreachable\")},\nb_(a,b,c,d){var s,r=c?J.pW(a,d):J.pV(a,d)\nif(a!==0&&b!=null)for(s=0;s<r.length;++s)r[s]=b\nreturn r},\npZ(a,b,c){var s,r=A.d([],c.h(\"w<0>\"))\nfor(s=J.M(a);s.k();)r.push(s.gm())\nif(b)return r\nreturn J.k8(r)},\nay(a,b,c){var s\nif(b)return A.pY(a,c)\ns=J.k8(A.pY(a,c))\nreturn s},\npY(a,b){var s,r\nif(Array.isArray(a))return A.d(a.slice(0),b.h(\"w<0>\"))\ns=A.d([],b.h(\"w<0>\"))\nfor(r=J.M(a);r.k();)s.push(r.gm())\nreturn s},\naG(a,b){var s=A.pZ(a,!1,b)\ns.fixed$length=Array\ns.immutable$list=Array\nreturn s},\nqh(a,b,c){var s,r,q,p,o\nA.ab(b,\"start\")\ns=c==null\nr=!s\nif(r){q=c-b\nif(q<0)throw A.a(A.a4(c,b,null,\"end\",null))\nif(q===0)return\"\"}if(Array.isArray(a)){p=a\no=p.length\nif(s)c=o\nreturn A.q6(b>0||c<o?p.slice(b,c):p)}if(t.Z.b(a))return A.uD(a,b,c)\nif(r)a=J.iT(a,c)\nif(b>0)a=J.dZ(a,b)\nreturn A.q6(A.ay(a,!0,t.S))},\nqg(a){return A.aA(a)},\nuD(a,b,c){var s=a.length\nif(b>=s)return\"\"\nreturn A.uz(a,b,c==null||c>s?s:c)},\nJ(a,b,c,d,e){return new A.cs(a,A.oz(a,d,b,e,c,!1))},\noH(a,b,c){var s=J.M(b)\nif(!s.k())return a\nif(c.length===0){do a+=A.u(s.gm())\nwhile(s.k())}else{a+=A.u(s.gm())\nfor(;s.k();)a=a+c+A.u(s.gm())}return a},\neF(){var s,r,q=A.up()\nif(q==null)throw A.a(A.H(\"'Uri.base' is not supported\"))\ns=$.qt\nif(s!=null&&q===$.qs)return s\nr=A.bm(q)\n$.qt=r\n$.qs=q\nreturn r},\nvx(a,b,c,d){var s,r,q,p,o,n=\"0123456789ABCDEF\"\nif(c===B.j){s=$.t9()\ns=s.b.test(b)}else s=!1\nif(s)return b\nr=B.i.a5(b)\nfor(s=r.length,q=0,p=\"\";q<s;++q){o=r[q]\nif(o<128&&(a[o>>>4]&1<<(o&15))!==0)p+=A.aA(o)\nelse p=d&&o===32?p+\"+\":p+\"%\"+n[o>>>4&15]+n[o&15]}return p.charCodeAt(0)==0?p:p},\noG(){return A.R(new Error())},\ntV(a){var s=Math.abs(a),r=a<0?\"-\":\"\"\nif(s>=1000)return\"\"+a\nif(s>=100)return r+\"0\"+s\nif(s>=10)return r+\"00\"+s\nreturn r+\"000\"+s},\npI(a){if(a>=100)return\"\"+a\nif(a>=10)return\"0\"+a\nreturn\"00\"+a},\nfO(a){if(a>=10)return\"\"+a\nreturn\"0\"+a},\npJ(a,b){return new A.bp(a+1000*b)},\nor(a,b){var s,r,q\nfor(s=a.length,r=0;r<s;++r){q=a[r]\nif(q.b===b)return q}throw A.a(A.ag(b,\"name\",\"No enum value with that name\"))},\ntY(a,b){var s,r,q=A.a3(t.N,b)\nfor(s=0;s<2;++s){r=a[s]\nq.q(0,r.b,r)}return q},\nfX(a){if(typeof a==\"number\"||A.bM(a)||a==null)return J.aU(a)\nif(typeof a==\"string\")return JSON.stringify(a)\nreturn A.q5(a)},\npM(a,b){A.aD(a,\"error\",t.K)\nA.aD(b,\"stackTrace\",t.l)\nA.tZ(a,b)},\ne_(a){return new A.fC(a)},\nK(a,b){return new A.aV(!1,null,b,a)},\nag(a,b,c){return new A.aV(!0,a,b,c)},\nbR(a,b){return a},\nkt(a,b){return new A.d7(null,null,!0,a,b,\"Value not in range\")},\na4(a,b,c,d,e){return new A.d7(b,c,!0,a,d,\"Invalid value\")},\nqa(a,b,c,d){if(a<b||a>c)throw A.a(A.a4(a,b,c,d,null))\nreturn a},\nb9(a,b,c){if(0>a||a>c)throw A.a(A.a4(a,0,c,\"start\",null))\nif(b!=null){if(a>b||b>c)throw A.a(A.a4(b,a,c,\"end\",null))\nreturn b}return c},\nab(a,b){if(a<0)throw A.a(A.a4(a,0,null,b,null))\nreturn a},\nh4(a,b,c,d,e){return new A.h3(b,!0,a,e,\"Index out of range\")},\nH(a){return new A.hL(a)},\nqp(a){return new A.hH(a)},\nB(a){return new A.b2(a)},\nax(a){return new A.fK(a)},\njL(a){return new A.id(a)},\nai(a,b,c){return new A.bs(a,b,c)},\nub(a,b,c){var s,r\nif(A.pk(a)){if(b===\"(\"&&c===\")\")return\"(...)\"\nreturn b+\"...\"+c}s=A.d([],t.s)\n$.cO.push(a)\ntry{A.w9(a,s)}finally{$.cO.pop()}r=A.oH(b,s,\", \")+c\nreturn r.charCodeAt(0)==0?r:r},\nox(a,b,c){var s,r\nif(A.pk(a))return b+\"...\"+c\ns=new A.av(b)\n$.cO.push(a)\ntry{r=s\nr.a=A.oH(r.a,a,\", \")}finally{$.cO.pop()}s.a+=c\nr=s.a\nreturn r.charCodeAt(0)==0?r:r},\nw9(a,b){var s,r,q,p,o,n,m,l=a.gt(a),k=0,j=0\nwhile(!0){if(!(k<80||j<3))break\nif(!l.k())return\ns=A.u(l.gm())\nb.push(s)\nk+=s.length+2;++j}if(!l.k()){if(j<=5)return\nr=b.pop()\nq=b.pop()}else{p=l.gm();++j\nif(!l.k()){if(j<=4){b.push(A.u(p))\nreturn}r=A.u(p)\nq=b.pop()\nk+=r.length+2}else{o=l.gm();++j\nfor(;l.k();p=o,o=n){n=l.gm();++j\nif(j>100){while(!0){if(!(k>75&&j>3))break\nk-=b.pop().length+2;--j}b.push(\"...\")\nreturn}}q=A.u(p)\nr=A.u(o)\nk+=r.length+q.length+4}}if(j>b.length+2){k+=5\nm=\"...\"}else m=null\nwhile(!0){if(!(k>80&&b.length>3))break\nk-=b.pop().length+2\nif(m==null){k+=5\nm=\"...\"}}if(m!=null)b.push(m)\nb.push(q)\nb.push(r)},\nes(a,b,c,d){var s\nif(B.f===c){s=J.aw(a)\nb=J.aw(b)\nreturn A.oI(A.c6(A.c6($.om(),s),b))}if(B.f===d){s=J.aw(a)\nb=J.aw(b)\nc=J.aw(c)\nreturn A.oI(A.c6(A.c6(A.c6($.om(),s),b),c))}s=J.aw(a)\nb=J.aw(b)\nc=J.aw(c)\nd=J.aw(d)\nd=A.oI(A.c6(A.c6(A.c6(A.c6($.om(),s),b),c),d))\nreturn d},\nxq(a){var s=A.u(a),r=$.rK\nif(r==null)A.pn(s)\nelse r.$1(s)},\nqr(a){var s,r=null,q=new A.av(\"\"),p=A.d([-1],t.t)\nA.uM(r,r,r,q,p)\np.push(q.a.length)\nq.a+=\",\"\nA.uL(B.p,B.ap.jO(a),q)\ns=q.a\nreturn new A.hN(s.charCodeAt(0)==0?s:s,p,r).geN()},\nbm(a5){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1,a2,a3=null,a4=a5.length\nif(a4>=5){s=((a5.charCodeAt(4)^58)*3|a5.charCodeAt(0)^100|a5.charCodeAt(1)^97|a5.charCodeAt(2)^116|a5.charCodeAt(3)^97)>>>0\nif(s===0)return A.qq(a4<a4?B.a.n(a5,0,a4):a5,5,a3).geN()\nelse if(s===32)return A.qq(B.a.n(a5,5,a4),0,a3).geN()}r=A.b_(8,0,!1,t.S)\nr[0]=0\nr[1]=-1\nr[2]=-1\nr[7]=-1\nr[3]=0\nr[4]=0\nr[5]=a4\nr[6]=a4\nif(A.rp(a5,0,a4,0,r)>=14)r[7]=a4\nq=r[1]\nif(q>=0)if(A.rp(a5,0,q,20,r)===20)r[7]=q\np=r[2]+1\no=r[3]\nn=r[4]\nm=r[5]\nl=r[6]\nif(l<m)m=l\nif(n<p)n=m\nelse if(n<=q)n=q+1\nif(o<p)o=n\nk=r[7]<0\nj=a3\nif(k){k=!1\nif(!(p>q+3)){i=o>0\nif(!(i&&o+1===n)){if(!B.a.E(a5,\"\\\\\",n))if(p>0)h=B.a.E(a5,\"\\\\\",p-1)||B.a.E(a5,\"\\\\\",p-2)\nelse h=!1\nelse h=!0\nif(!h){if(!(m<a4&&m===n+2&&B.a.E(a5,\"..\",n)))h=m>n+2&&B.a.E(a5,\"/..\",m-3)\nelse h=!0\nif(!h)if(q===4){if(B.a.E(a5,\"file\",0)){if(p<=0){if(!B.a.E(a5,\"/\",n)){g=\"file:///\"\ns=3}else{g=\"file://\"\ns=2}a5=g+B.a.n(a5,n,a4)\nm+=s\nl+=s\na4=a5.length\np=7\no=7\nn=7}else if(n===m){++l\nf=m+1\na5=B.a.aO(a5,n,m,\"/\");++a4\nm=f}j=\"file\"}else if(B.a.E(a5,\"http\",0)){if(i&&o+3===n&&B.a.E(a5,\"80\",o+1)){l-=3\ne=n-3\nm-=3\na5=B.a.aO(a5,o,n,\"\")\na4-=3\nn=e}j=\"http\"}}else if(q===5&&B.a.E(a5,\"https\",0)){if(i&&o+4===n&&B.a.E(a5,\"443\",o+1)){l-=4\ne=n-4\nm-=4\na5=B.a.aO(a5,o,n,\"\")\na4-=3\nn=e}j=\"https\"}k=!h}}}}if(k)return new A.b4(a4<a5.length?B.a.n(a5,0,a4):a5,q,p,o,n,m,l,j)\nif(j==null)if(q>0)j=A.nC(a5,0,q)\nelse{if(q===0)A.dL(a5,0,\"Invalid empty scheme\")\nj=\"\"}d=a3\nif(p>0){c=q+3\nb=c<p?A.r1(a5,c,p-1):\"\"\na=A.qZ(a5,p,o,!1)\ni=o+1\nif(i<n){a0=A.q4(B.a.n(a5,i,n),a3)\nd=A.nB(a0==null?A.y(A.ai(\"Invalid port\",a5,i)):a0,j)}}else{a=a3\nb=\"\"}a1=A.r_(a5,n,m,a3,j,a!=null)\na2=m<l?A.r0(a5,m+1,l,a3):a3\nreturn A.fk(j,b,a,d,a1,a2,l<a4?A.qY(a5,l+1,a4):a3)},\nuO(a){return A.p4(a,0,a.length,B.j,!1)},\nuN(a,b,c){var s,r,q,p,o,n,m=\"IPv4 address should contain exactly 4 parts\",l=\"each part must be in the range 0..255\",k=new A.lh(a),j=new Uint8Array(4)\nfor(s=b,r=s,q=0;s<c;++s){p=a.charCodeAt(s)\nif(p!==46){if((p^48)>9)k.$2(\"invalid character\",s)}else{if(q===3)k.$2(m,s)\no=A.aN(B.a.n(a,r,s),null)\nif(o>255)k.$2(l,r)\nn=q+1\nj[q]=o\nr=s+1\nq=n}}if(q!==3)k.$2(m,c)\no=A.aN(B.a.n(a,r,c),null)\nif(o>255)k.$2(l,r)\nj[q]=o\nreturn j},\nqu(a,b,a0){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e=null,d=new A.li(a),c=new A.lj(d,a)\nif(a.length<2)d.$2(\"address is too short\",e)\ns=A.d([],t.t)\nfor(r=b,q=r,p=!1,o=!1;r<a0;++r){n=a.charCodeAt(r)\nif(n===58){if(r===b){++r\nif(a.charCodeAt(r)!==58)d.$2(\"invalid start colon.\",r)\nq=r}if(r===q){if(p)d.$2(\"only one wildcard `::` is allowed\",r)\ns.push(-1)\np=!0}else s.push(c.$2(q,r))\nq=r+1}else if(n===46)o=!0}if(s.length===0)d.$2(\"too few parts\",e)\nm=q===a0\nl=B.c.gC(s)\nif(m&&l!==-1)d.$2(\"expected a part after last `:`\",a0)\nif(!m)if(!o)s.push(c.$2(q,a0))\nelse{k=A.uN(a,q,a0)\ns.push((k[0]<<8|k[1])>>>0)\ns.push((k[2]<<8|k[3])>>>0)}if(p){if(s.length>7)d.$2(\"an address with a wildcard must have less than 7 parts\",e)}else if(s.length!==8)d.$2(\"an address without a wildcard must contain exactly 8 parts\",e)\nj=new Uint8Array(16)\nfor(l=s.length,i=9-l,r=0,h=0;r<l;++r){g=s[r]\nif(g===-1)for(f=0;f<i;++f){j[h]=0\nj[h+1]=0\nh+=2}else{j[h]=B.b.P(g,8)\nj[h+1]=g&255\nh+=2}}return j},\nfk(a,b,c,d,e,f,g){return new A.fj(a,b,c,d,e,f,g)},\naj(a,b,c,d){var s,r,q,p,o,n,m,l,k=null\nd=d==null?\"\":A.nC(d,0,d.length)\ns=A.r1(k,0,0)\na=A.qZ(a,0,a==null?0:a.length,!1)\nr=A.r0(k,0,0,k)\nq=A.qY(k,0,0)\np=A.nB(k,d)\no=d===\"file\"\nif(a==null)n=s.length!==0||p!=null||o\nelse n=!1\nif(n)a=\"\"\nn=a==null\nm=!n\nb=A.r_(b,0,b==null?0:b.length,c,d,m)\nl=d.length===0\nif(l&&n&&!B.a.u(b,\"/\"))b=A.p3(b,!l||m)\nelse b=A.cJ(b)\nreturn A.fk(d,s,n&&B.a.u(b,\"//\")?\"\":a,p,b,r,q)},\nqV(a){if(a===\"http\")return 80\nif(a===\"https\")return 443\nreturn 0},\ndL(a,b,c){throw A.a(A.ai(c,a,b))},\nqU(a,b){return b?A.vt(a,!1):A.vs(a,!1)},\nvo(a,b){var s,r,q\nfor(s=a.length,r=0;r<s;++r){q=a[r]\nif(J.pz(q,\"/\")){s=A.H(\"Illegal path character \"+A.u(q))\nthrow A.a(s)}}},\nnz(a,b,c){var s,r,q\nfor(s=A.b3(a,c,null,A.Q(a).c),r=s.$ti,s=new A.aZ(s,s.gl(0),r.h(\"aZ<P.E>\")),r=r.h(\"P.E\");s.k();){q=s.d\nif(q==null)q=r.a(q)\nif(B.a.M(q,A.J('[\"*/:<>?\\\\\\\\|]',!0,!1,!1,!1)))if(b)throw A.a(A.K(\"Illegal character in path\",null))\nelse throw A.a(A.H(\"Illegal character in path: \"+q))}},\nvp(a,b){var s,r=\"Illegal drive letter \"\nif(!(65<=a&&a<=90))s=97<=a&&a<=122\nelse s=!0\nif(s)return\nif(b)throw A.a(A.K(r+A.qg(a),null))\nelse throw A.a(A.H(r+A.qg(a)))},\nvs(a,b){var s=null,r=A.d(a.split(\"/\"),t.s)\nif(B.a.u(a,\"/\"))return A.aj(s,s,r,\"file\")\nelse return A.aj(s,s,r,s)},\nvt(a,b){var s,r,q,p,o=\"\\\\\",n=null,m=\"file\"\nif(B.a.u(a,\"\\\\\\\\?\\\\\"))if(B.a.E(a,\"UNC\\\\\",4))a=B.a.aO(a,0,7,o)\nelse{a=B.a.K(a,4)\nif(a.length<3||a.charCodeAt(1)!==58||a.charCodeAt(2)!==92)throw A.a(A.ag(a,\"path\",\"Windows paths with \\\\\\\\?\\\\ prefix must be absolute\"))}else a=A.bc(a,\"/\",o)\ns=a.length\nif(s>1&&a.charCodeAt(1)===58){A.vp(a.charCodeAt(0),!0)\nif(s===2||a.charCodeAt(2)!==92)throw A.a(A.ag(a,\"path\",\"Windows paths with drive letter must be absolute\"))\nr=A.d(a.split(o),t.s)\nA.nz(r,!0,1)\nreturn A.aj(n,n,r,m)}if(B.a.u(a,o))if(B.a.E(a,o,1)){q=B.a.aW(a,o,2)\ns=q<0\np=s?B.a.K(a,2):B.a.n(a,2,q)\nr=A.d((s?\"\":B.a.K(a,q+1)).split(o),t.s)\nA.nz(r,!0,0)\nreturn A.aj(p,n,r,m)}else{r=A.d(a.split(o),t.s)\nA.nz(r,!0,0)\nreturn A.aj(n,n,r,m)}else{r=A.d(a.split(o),t.s)\nA.nz(r,!0,0)\nreturn A.aj(n,n,r,n)}},\nnB(a,b){if(a!=null&&a===A.qV(b))return null\nreturn a},\nqZ(a,b,c,d){var s,r,q,p,o,n\nif(a==null)return null\nif(b===c)return\"\"\nif(a.charCodeAt(b)===91){s=c-1\nif(a.charCodeAt(s)!==93)A.dL(a,b,\"Missing end `]` to match `[` in host\")\nr=b+1\nq=A.vq(a,r,s)\nif(q<s){p=q+1\no=A.r4(a,B.a.E(a,\"25\",p)?q+3:p,s,\"%25\")}else o=\"\"\nA.qu(a,r,q)\nreturn B.a.n(a,b,q).toLowerCase()+o+\"]\"}for(n=b;n<c;++n)if(a.charCodeAt(n)===58){q=B.a.aW(a,\"%\",b)\nq=q>=b&&q<c?q:c\nif(q<c){p=q+1\no=A.r4(a,B.a.E(a,\"25\",p)?q+3:p,c,\"%25\")}else o=\"\"\nA.qu(a,b,q)\nreturn\"[\"+B.a.n(a,b,q)+o+\"]\"}return A.vv(a,b,c)},\nvq(a,b,c){var s=B.a.aW(a,\"%\",b)\nreturn s>=b&&s<c?s:c},\nr4(a,b,c,d){var s,r,q,p,o,n,m,l,k,j,i=d!==\"\"?new A.av(d):null\nfor(s=b,r=s,q=!0;s<c;){p=a.charCodeAt(s)\nif(p===37){o=A.p2(a,s,!0)\nn=o==null\nif(n&&q){s+=3\ncontinue}if(i==null)i=new A.av(\"\")\nm=i.a+=B.a.n(a,r,s)\nif(n)o=B.a.n(a,s,s+3)\nelse if(o===\"%\")A.dL(a,s,\"ZoneID should not contain % anymore\")\ni.a=m+o\ns+=3\nr=s\nq=!0}else if(p<127&&(B.ab[p>>>4]&1<<(p&15))!==0){if(q&&65<=p&&90>=p){if(i==null)i=new A.av(\"\")\nif(r<s){i.a+=B.a.n(a,r,s)\nr=s}q=!1}++s}else{l=1\nif((p&64512)===55296&&s+1<c){k=a.charCodeAt(s+1)\nif((k&64512)===56320){p=(p&1023)<<10|k&1023|65536\nl=2}}j=B.a.n(a,r,s)\nif(i==null){i=new A.av(\"\")\nn=i}else n=i\nn.a+=j\nm=A.p1(p)\nn.a+=m\ns+=l\nr=s}}if(i==null)return B.a.n(a,b,c)\nif(r<c){j=B.a.n(a,r,c)\ni.a+=j}n=i.a\nreturn n.charCodeAt(0)==0?n:n},\nvv(a,b,c){var s,r,q,p,o,n,m,l,k,j,i\nfor(s=b,r=s,q=null,p=!0;s<c;){o=a.charCodeAt(s)\nif(o===37){n=A.p2(a,s,!0)\nm=n==null\nif(m&&p){s+=3\ncontinue}if(q==null)q=new A.av(\"\")\nl=B.a.n(a,r,s)\nif(!p)l=l.toLowerCase()\nk=q.a+=l\nj=3\nif(m)n=B.a.n(a,s,s+3)\nelse if(n===\"%\"){n=\"%25\"\nj=1}q.a=k+n\ns+=j\nr=s\np=!0}else if(o<127&&(B.aM[o>>>4]&1<<(o&15))!==0){if(p&&65<=o&&90>=o){if(q==null)q=new A.av(\"\")\nif(r<s){q.a+=B.a.n(a,r,s)\nr=s}p=!1}++s}else if(o<=93&&(B.a6[o>>>4]&1<<(o&15))!==0)A.dL(a,s,\"Invalid character\")\nelse{j=1\nif((o&64512)===55296&&s+1<c){i=a.charCodeAt(s+1)\nif((i&64512)===56320){o=(o&1023)<<10|i&1023|65536\nj=2}}l=B.a.n(a,r,s)\nif(!p)l=l.toLowerCase()\nif(q==null){q=new A.av(\"\")\nm=q}else m=q\nm.a+=l\nk=A.p1(o)\nm.a+=k\ns+=j\nr=s}}if(q==null)return B.a.n(a,b,c)\nif(r<c){l=B.a.n(a,r,c)\nif(!p)l=l.toLowerCase()\nq.a+=l}m=q.a\nreturn m.charCodeAt(0)==0?m:m},\nnC(a,b,c){var s,r,q\nif(b===c)return\"\"\nif(!A.qX(a.charCodeAt(b)))A.dL(a,b,\"Scheme not starting with alphabetic character\")\nfor(s=b,r=!1;s<c;++s){q=a.charCodeAt(s)\nif(!(q<128&&(B.a4[q>>>4]&1<<(q&15))!==0))A.dL(a,s,\"Illegal scheme character\")\nif(65<=q&&q<=90)r=!0}a=B.a.n(a,b,c)\nreturn A.vn(r?a.toLowerCase():a)},\nvn(a){if(a===\"http\")return\"http\"\nif(a===\"file\")return\"file\"\nif(a===\"https\")return\"https\"\nif(a===\"package\")return\"package\"\nreturn a},\nr1(a,b,c){if(a==null)return\"\"\nreturn A.fl(a,b,c,B.aL,!1,!1)},\nr_(a,b,c,d,e,f){var s,r=e===\"file\",q=r||f\nif(a==null){if(d==null)return r?\"/\":\"\"\ns=new A.D(d,new A.nA(),A.Q(d).h(\"D<1,j>\")).aq(0,\"/\")}else if(d!=null)throw A.a(A.K(\"Both path and pathSegments specified\",null))\nelse s=A.fl(a,b,c,B.a5,!0,!0)\nif(s.length===0){if(r)return\"/\"}else if(q&&!B.a.u(s,\"/\"))s=\"/\"+s\nreturn A.vu(s,e,f)},\nvu(a,b,c){var s=b.length===0\nif(s&&!c&&!B.a.u(a,\"/\")&&!B.a.u(a,\"\\\\\"))return A.p3(a,!s||c)\nreturn A.cJ(a)},\nr0(a,b,c,d){if(a!=null)return A.fl(a,b,c,B.p,!0,!1)\nreturn null},\nqY(a,b,c){if(a==null)return null\nreturn A.fl(a,b,c,B.p,!0,!1)},\np2(a,b,c){var s,r,q,p,o,n=b+2\nif(n>=a.length)return\"%\"\ns=a.charCodeAt(b+1)\nr=a.charCodeAt(n)\nq=A.o5(s)\np=A.o5(r)\nif(q<0||p<0)return\"%\"\no=q*16+p\nif(o<127&&(B.ab[B.b.P(o,4)]&1<<(o&15))!==0)return A.aA(c&&65<=o&&90>=o?(o|32)>>>0:o)\nif(s>=97||r>=97)return B.a.n(a,b,b+3).toUpperCase()\nreturn null},\np1(a){var s,r,q,p,o,n=\"0123456789ABCDEF\"\nif(a<128){s=new Uint8Array(3)\ns[0]=37\ns[1]=n.charCodeAt(a>>>4)\ns[2]=n.charCodeAt(a&15)}else{if(a>2047)if(a>65535){r=240\nq=4}else{r=224\nq=3}else{r=192\nq=2}s=new Uint8Array(3*q)\nfor(p=0;--q,q>=0;r=128){o=B.b.ja(a,6*q)&63|r\ns[p]=37\ns[p+1]=n.charCodeAt(o>>>4)\ns[p+2]=n.charCodeAt(o&15)\np+=3}}return A.qh(s,0,null)},\nfl(a,b,c,d,e,f){var s=A.r3(a,b,c,d,e,f)\nreturn s==null?B.a.n(a,b,c):s},\nr3(a,b,c,d,e,f){var s,r,q,p,o,n,m,l,k,j,i=null\nfor(s=!e,r=b,q=r,p=i;r<c;){o=a.charCodeAt(r)\nif(o<127&&(d[o>>>4]&1<<(o&15))!==0)++r\nelse{n=1\nif(o===37){m=A.p2(a,r,!1)\nif(m==null){r+=3\ncontinue}if(\"%\"===m)m=\"%25\"\nelse n=3}else if(o===92&&f)m=\"/\"\nelse if(s&&o<=93&&(B.a6[o>>>4]&1<<(o&15))!==0){A.dL(a,r,\"Invalid character\")\nn=i\nm=n}else{if((o&64512)===55296){l=r+1\nif(l<c){k=a.charCodeAt(l)\nif((k&64512)===56320){o=(o&1023)<<10|k&1023|65536\nn=2}}}m=A.p1(o)}if(p==null){p=new A.av(\"\")\nl=p}else l=p\nj=l.a+=B.a.n(a,q,r)\nl.a=j+A.u(m)\nr+=n\nq=r}}if(p==null)return i\nif(q<c){s=B.a.n(a,q,c)\np.a+=s}s=p.a\nreturn s.charCodeAt(0)==0?s:s},\nr2(a){if(B.a.u(a,\".\"))return!0\nreturn B.a.k7(a,\"/.\")!==-1},\ncJ(a){var s,r,q,p,o,n\nif(!A.r2(a))return a\ns=A.d([],t.s)\nfor(r=a.split(\"/\"),q=r.length,p=!1,o=0;o<q;++o){n=r[o]\nif(J.X(n,\"..\")){if(s.length!==0){s.pop()\nif(s.length===0)s.push(\"\")}p=!0}else{p=\".\"===n\nif(!p)s.push(n)}}if(p)s.push(\"\")\nreturn B.c.aq(s,\"/\")},\np3(a,b){var s,r,q,p,o,n\nif(!A.r2(a))return!b?A.qW(a):a\ns=A.d([],t.s)\nfor(r=a.split(\"/\"),q=r.length,p=!1,o=0;o<q;++o){n=r[o]\nif(\"..\"===n){p=s.length!==0&&B.c.gC(s)!==\"..\"\nif(p)s.pop()\nelse s.push(\"..\")}else{p=\".\"===n\nif(!p)s.push(n)}}r=s.length\nif(r!==0)r=r===1&&s[0].length===0\nelse r=!0\nif(r)return\"./\"\nif(p||B.c.gC(s)===\"..\")s.push(\"\")\nif(!b)s[0]=A.qW(s[0])\nreturn B.c.aq(s,\"/\")},\nqW(a){var s,r,q=a.length\nif(q>=2&&A.qX(a.charCodeAt(0)))for(s=1;s<q;++s){r=a.charCodeAt(s)\nif(r===58)return B.a.n(a,0,s)+\"%3A\"+B.a.K(a,s+1)\nif(r>127||(B.a4[r>>>4]&1<<(r&15))===0)break}return a},\nvw(a,b){if(a.kc(\"package\")&&a.c==null)return A.rr(b,0,b.length)\nreturn-1},\nvr(a,b){var s,r,q\nfor(s=0,r=0;r<2;++r){q=a.charCodeAt(b+r)\nif(48<=q&&q<=57)s=s*16+q-48\nelse{q|=32\nif(97<=q&&q<=102)s=s*16+q-87\nelse throw A.a(A.K(\"Invalid URL encoding\",null))}}return s},\np4(a,b,c,d,e){var s,r,q,p,o=b\nwhile(!0){if(!(o<c)){s=!0\nbreak}r=a.charCodeAt(o)\nif(r<=127)q=r===37\nelse q=!0\nif(q){s=!1\nbreak}++o}if(s)if(B.j===d)return B.a.n(a,b,c)\nelse p=new A.e6(B.a.n(a,b,c))\nelse{p=A.d([],t.t)\nfor(q=a.length,o=b;o<c;++o){r=a.charCodeAt(o)\nif(r>127)throw A.a(A.K(\"Illegal percent encoding in URI\",null))\nif(r===37){if(o+3>q)throw A.a(A.K(\"Truncated URI\",null))\np.push(A.vr(a,o+1))\no+=2}else p.push(r)}}return d.cT(p)},\nqX(a){var s=a|32\nreturn 97<=s&&s<=122},\nuM(a,b,c,d,e){d.a=d.a},\nqq(a,b,c){var s,r,q,p,o,n,m,l,k=\"Invalid MIME type\",j=A.d([b-1],t.t)\nfor(s=a.length,r=b,q=-1,p=null;r<s;++r){p=a.charCodeAt(r)\nif(p===44||p===59)break\nif(p===47){if(q<0){q=r\ncontinue}throw A.a(A.ai(k,a,r))}}if(q<0&&r>b)throw A.a(A.ai(k,a,r))\nfor(;p!==44;){j.push(r);++r\nfor(o=-1;r<s;++r){p=a.charCodeAt(r)\nif(p===61){if(o<0)o=r}else if(p===59||p===44)break}if(o>=0)j.push(o)\nelse{n=B.c.gC(j)\nif(p!==44||r!==n+7||!B.a.E(a,\"base64\",n+1))throw A.a(A.ai(\"Expecting '='\",a,r))\nbreak}}j.push(r)\nm=r+1\nif((j.length&1)===1)a=B.aq.kh(a,m,s)\nelse{l=A.r3(a,m,s,B.p,!0,!1)\nif(l!=null)a=B.a.aO(a,m,s,l)}return new A.hN(a,j,c)},\nuL(a,b,c){var s,r,q,p,o,n=\"0123456789ABCDEF\"\nfor(s=b.length,r=0,q=0;q<s;++q){p=b[q]\nr|=p\nif(p<128&&(a[p>>>4]&1<<(p&15))!==0){o=A.aA(p)\nc.a+=o}else{o=A.aA(37)\nc.a+=o\no=A.aA(n.charCodeAt(p>>>4))\nc.a+=o\no=A.aA(n.charCodeAt(p&15))\nc.a+=o}}if((r&4294967040)!==0)for(q=0;q<s;++q){p=b[q]\nif(p>255)throw A.a(A.ag(p,\"non-byte value\",null))}},\nvP(){var s,r,q,p,o,n=\"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~!$&'()*+,;=\",m=\".\",l=\":\",k=\"/\",j=\"\\\\\",i=\"?\",h=\"#\",g=\"/\\\\\",f=J.pU(22,t.p)\nfor(s=0;s<22;++s)f[s]=new Uint8Array(96)\nr=new A.nN(f)\nq=new A.nO()\np=new A.nP()\no=r.$2(0,225)\nq.$3(o,n,1)\nq.$3(o,m,14)\nq.$3(o,l,34)\nq.$3(o,k,3)\nq.$3(o,j,227)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(14,225)\nq.$3(o,n,1)\nq.$3(o,m,15)\nq.$3(o,l,34)\nq.$3(o,g,234)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(15,225)\nq.$3(o,n,1)\nq.$3(o,\"%\",225)\nq.$3(o,l,34)\nq.$3(o,k,9)\nq.$3(o,j,233)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(1,225)\nq.$3(o,n,1)\nq.$3(o,l,34)\nq.$3(o,k,10)\nq.$3(o,j,234)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(2,235)\nq.$3(o,n,139)\nq.$3(o,k,131)\nq.$3(o,j,131)\nq.$3(o,m,146)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(3,235)\nq.$3(o,n,11)\nq.$3(o,k,68)\nq.$3(o,j,68)\nq.$3(o,m,18)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(4,229)\nq.$3(o,n,5)\np.$3(o,\"AZ\",229)\nq.$3(o,l,102)\nq.$3(o,\"@\",68)\nq.$3(o,\"[\",232)\nq.$3(o,k,138)\nq.$3(o,j,138)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(5,229)\nq.$3(o,n,5)\np.$3(o,\"AZ\",229)\nq.$3(o,l,102)\nq.$3(o,\"@\",68)\nq.$3(o,k,138)\nq.$3(o,j,138)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(6,231)\np.$3(o,\"19\",7)\nq.$3(o,\"@\",68)\nq.$3(o,k,138)\nq.$3(o,j,138)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(7,231)\np.$3(o,\"09\",7)\nq.$3(o,\"@\",68)\nq.$3(o,k,138)\nq.$3(o,j,138)\nq.$3(o,i,172)\nq.$3(o,h,205)\nq.$3(r.$2(8,8),\"]\",5)\no=r.$2(9,235)\nq.$3(o,n,11)\nq.$3(o,m,16)\nq.$3(o,g,234)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(16,235)\nq.$3(o,n,11)\nq.$3(o,m,17)\nq.$3(o,g,234)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(17,235)\nq.$3(o,n,11)\nq.$3(o,k,9)\nq.$3(o,j,233)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(10,235)\nq.$3(o,n,11)\nq.$3(o,m,18)\nq.$3(o,k,10)\nq.$3(o,j,234)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(18,235)\nq.$3(o,n,11)\nq.$3(o,m,19)\nq.$3(o,g,234)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(19,235)\nq.$3(o,n,11)\nq.$3(o,g,234)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(11,235)\nq.$3(o,n,11)\nq.$3(o,k,10)\nq.$3(o,j,234)\nq.$3(o,i,172)\nq.$3(o,h,205)\no=r.$2(12,236)\nq.$3(o,n,12)\nq.$3(o,i,12)\nq.$3(o,h,205)\no=r.$2(13,237)\nq.$3(o,n,13)\nq.$3(o,i,13)\np.$3(r.$2(20,245),\"az\",21)\no=r.$2(21,245)\np.$3(o,\"az\",21)\np.$3(o,\"09\",21)\nq.$3(o,\"+-.\",21)\nreturn f},\nrp(a,b,c,d,e){var s,r,q,p,o=$.tn()\nfor(s=b;s<c;++s){r=o[d]\nq=a.charCodeAt(s)^96\np=r[q>95?31:q]\nd=p&31\ne[p>>>5]=s}return d},\nqN(a){if(a.b===7&&B.a.u(a.a,\"package\")&&a.c<=0)return A.rr(a.a,a.e,a.f)\nreturn-1},\nrr(a,b,c){var s,r,q\nfor(s=b,r=0;s<c;++s){q=a.charCodeAt(s)\nif(q===47)return r!==0?s:-1\nif(q===37||q===58)return-1\nr|=q^46}return-1},\nvM(a,b,c){var s,r,q,p,o,n\nfor(s=a.length,r=0,q=0;q<s;++q){p=b.charCodeAt(c+q)\no=a.charCodeAt(q)^p\nif(o!==0){if(o===32){n=p|o\nif(97<=n&&n<=122){r=32\ncontinue}}return-1}}return r},\na6:function a6(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nm_:function m_(){},\nm0:function m0(){},\nie:function ie(a,b){this.a=a\nthis.$ti=b},\nfN:function fN(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nbp:function bp(a){this.a=a},\nmd:function md(){},\nO:function O(){},\nfC:function fC(a){this.a=a},\nbD:function bD(){},\naV:function aV(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\nd7:function d7(a,b,c,d,e,f){var _=this\n_.e=a\n_.f=b\n_.a=c\n_.b=d\n_.c=e\n_.d=f},\nh3:function h3(a,b,c,d,e){var _=this\n_.f=a\n_.a=b\n_.b=c\n_.c=d\n_.d=e},\nhL:function hL(a){this.a=a},\nhH:function hH(a){this.a=a},\nb2:function b2(a){this.a=a},\nfK:function fK(a){this.a=a},\nhq:function hq(){},\neA:function eA(){},\nid:function id(a){this.a=a},\nbs:function bs(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nh6:function h6(){},\nf:function f(){},\nbv:function bv(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\nF:function F(){},\ne:function e(){},\ndI:function dI(a){this.a=a},\nav:function av(a){this.a=a},\nlh:function lh(a){this.a=a},\nli:function li(a){this.a=a},\nlj:function lj(a,b){this.a=a\nthis.b=b},\nfj:function fj(a,b,c,d,e,f,g){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f\n_.r=g\n_.y=_.x=_.w=$},\nnA:function nA(){},\nhN:function hN(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nnN:function nN(a){this.a=a},\nnO:function nO(){},\nnP:function nP(){},\nb4:function b4(a,b,c,d,e,f,g,h){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f\n_.r=g\n_.w=h\n_.x=null},\ni9:function i9(a,b,c,d,e,f,g){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f\n_.r=g\n_.y=_.x=_.w=$},\nfZ:function fZ(a){this.a=a},\nbb(a){var s\nif(typeof a==\"function\")throw A.a(A.K(\"Attempting to rewrap a JS function.\",null))\ns=function(b,c){return function(d){return b(c,d,arguments.length)}}(A.vF,a)\ns[$.dX()]=a\nreturn s},\ncL(a){var s\nif(typeof a==\"function\")throw A.a(A.K(\"Attempting to rewrap a JS function.\",null))\ns=function(b,c){return function(d,e){return b(c,d,e,arguments.length)}}(A.vG,a)\ns[$.dX()]=a\nreturn s},\niK(a){var s\nif(typeof a==\"function\")throw A.a(A.K(\"Attempting to rewrap a JS function.\",null))\ns=function(b,c){return function(d,e,f){return b(c,d,e,f,arguments.length)}}(A.vH,a)\ns[$.dX()]=a\nreturn s},\nnR(a){var s\nif(typeof a==\"function\")throw A.a(A.K(\"Attempting to rewrap a JS function.\",null))\ns=function(b,c){return function(d,e,f,g){return b(c,d,e,f,g,arguments.length)}}(A.vI,a)\ns[$.dX()]=a\nreturn s},\np7(a){var s\nif(typeof a==\"function\")throw A.a(A.K(\"Attempting to rewrap a JS function.\",null))\ns=function(b,c){return function(d,e,f,g,h){return b(c,d,e,f,g,h,arguments.length)}}(A.vJ,a)\ns[$.dX()]=a\nreturn s},\nvF(a,b,c){if(c>=1)return a.$1(b)\nreturn a.$0()},\nvG(a,b,c,d){if(d>=2)return a.$2(b,c)\nif(d===1)return a.$1(b)\nreturn a.$0()},\nvH(a,b,c,d,e){if(e>=3)return a.$3(b,c,d)\nif(e===2)return a.$2(b,c)\nif(e===1)return a.$1(b)\nreturn a.$0()},\nvI(a,b,c,d,e,f){if(f>=4)return a.$4(b,c,d,e)\nif(f===3)return a.$3(b,c,d)\nif(f===2)return a.$2(b,c)\nif(f===1)return a.$1(b)\nreturn a.$0()},\nvJ(a,b,c,d,e,f,g){if(g>=5)return a.$5(b,c,d,e,f)\nif(g===4)return a.$4(b,c,d,e)\nif(g===3)return a.$3(b,c,d)\nif(g===2)return a.$2(b,c)\nif(g===1)return a.$1(b)\nreturn a.$0()},\nrj(a){return a==null||A.bM(a)||typeof a==\"number\"||typeof a==\"string\"||t.gj.b(a)||t.p.b(a)||t.go.b(a)||t.dQ.b(a)||t.h7.b(a)||t.an.b(a)||t.bv.b(a)||t.h4.b(a)||t.gN.b(a)||t.E.b(a)||t.fd.b(a)},\nxe(a){if(A.rj(a))return a\nreturn new A.oa(new A.dw(t.hg)).$1(a)},\ncM(a,b,c){return a[b].apply(a,c)},\ndT(a,b){var s,r\nif(b==null)return new a()\nif(b instanceof Array)switch(b.length){case 0:return new a()\ncase 1:return new a(b[0])\ncase 2:return new a(b[0],b[1])\ncase 3:return new a(b[0],b[1],b[2])\ncase 4:return new a(b[0],b[1],b[2],b[3])}s=[null]\nB.c.aJ(s,b)\nr=a.bind.apply(a,s)\nString(r)\nreturn new r()},\na_(a,b){var s=new A.k($.i,b.h(\"k<0>\")),r=new A.a2(s,b.h(\"a2<0>\"))\na.then(A.cf(new A.oe(r),1),A.cf(new A.of(r),1))\nreturn s},\nri(a){return a==null||typeof a===\"boolean\"||typeof a===\"number\"||typeof a===\"string\"||a instanceof Int8Array||a instanceof Uint8Array||a instanceof Uint8ClampedArray||a instanceof Int16Array||a instanceof Uint16Array||a instanceof Int32Array||a instanceof Uint32Array||a instanceof Float32Array||a instanceof Float64Array||a instanceof ArrayBuffer||a instanceof DataView},\nry(a){if(A.ri(a))return a\nreturn new A.o1(new A.dw(t.hg)).$1(a)},\noa:function oa(a){this.a=a},\noe:function oe(a){this.a=a},\nof:function of(a){this.a=a},\no1:function o1(a){this.a=a},\nho:function ho(a){this.a=a},\nrF(a,b){return Math.max(a,b)},\nxu(a){return Math.sqrt(a)},\nxt(a){return Math.sin(a)},\nwV(a){return Math.cos(a)},\nxA(a){return Math.tan(a)},\nww(a){return Math.acos(a)},\nwx(a){return Math.asin(a)},\nwR(a){return Math.atan(a)},\nnc:function nc(a){this.a=a},\ncU:function cU(){},\nfP:function fP(){},\nhf:function hf(){},\nhn:function hn(){},\nhK:function hK(){},\ntW(a,b){var s=new A.ea(a,b,A.a3(t.S,t.aR),A.eD(null,null,!0,t.al),new A.a2(new A.k($.i,t.D),t.h))\ns.hK(a,!1,b)\nreturn s},\nea:function ea(a,b,c,d,e){var _=this\n_.a=a\n_.c=b\n_.d=0\n_.e=c\n_.f=d\n_.r=!1\n_.w=e},\njA:function jA(a){this.a=a},\njB:function jB(a,b){this.a=a\nthis.b=b},\nir:function ir(a,b){this.a=a\nthis.b=b},\nfL:function fL(){},\nfT:function fT(a){this.a=a},\nfS:function fS(){},\njC:function jC(a){this.a=a},\njD:function jD(a){this.a=a},\nbZ:function bZ(){},\nam:function am(a,b){this.a=a\nthis.b=b},\nba:function ba(a,b){this.a=a\nthis.b=b},\naH:function aH(a){this.a=a},\nbq:function bq(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nbo:function bo(a){this.a=a},\nd3:function d3(a,b){this.a=a\nthis.b=b},\ncv:function cv(a,b){this.a=a\nthis.b=b},\nbU:function bU(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\nc1:function c1(a){this.a=a},\nbg:function bg(a,b){this.a=a\nthis.b=b},\nc0:function c0(a,b){this.a=a\nthis.b=b},\nc3:function c3(a,b){this.a=a\nthis.b=b},\nbT:function bT(a,b){this.a=a\nthis.b=b},\nc4:function c4(a){this.a=a},\nc2:function c2(a,b){this.a=a\nthis.b=b},\nby:function by(a){this.a=a},\nbA:function bA(a){this.a=a},\nuC(a,b,c){var s=null,r=t.S,q=A.d([],t.t)\nr=new A.kC(a,!1,!0,A.a3(r,t.x),A.a3(r,t.g1),q,new A.fd(s,s,t.dn),A.oC(t.gw),new A.a2(new A.k($.i,t.D),t.h),A.eD(s,s,!1,t.bw))\nr.hM(a,!1,!0)\nreturn r},\nkC:function kC(a,b,c,d,e,f,g,h,i,j){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.f=_.e=0\n_.r=e\n_.w=f\n_.x=g\n_.y=!1\n_.z=h\n_.Q=i\n_.as=j},\nkH:function kH(a){this.a=a},\nkI:function kI(a,b){this.a=a\nthis.b=b},\nkJ:function kJ(a,b){this.a=a\nthis.b=b},\nkD:function kD(a,b){this.a=a\nthis.b=b},\nkE:function kE(a,b){this.a=a\nthis.b=b},\nkG:function kG(a,b){this.a=a\nthis.b=b},\nkF:function kF(a){this.a=a},\nf7:function f7(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nhX:function hX(){},\nlK:function lK(a,b){this.a=a\nthis.b=b},\nlL:function lL(a,b){this.a=a\nthis.b=b},\nlI:function lI(){},\nlE:function lE(a,b){this.a=a\nthis.b=b},\nlF:function lF(){},\nlG:function lG(){},\nlD:function lD(){},\nlJ:function lJ(){},\nlH:function lH(){},\ndi:function di(a,b){this.a=a\nthis.b=b},\nbC:function bC(a,b){this.a=a\nthis.b=b},\nxr(a,b){var s,r,q={}\nq.a=s\nq.a=null\ns=new A.bS(new A.a8(new A.k($.i,b.h(\"k<0>\")),b.h(\"a8<0>\")),A.d([],t.bT),b.h(\"bS<0>\"))\nq.a=s\nr=t.X\nA.xs(new A.og(q,a,b),A.kf([B.ah,s],r,r),t.H)\nreturn q.a},\nrx(){var s=$.i.i(0,B.ah)\nif(s instanceof A.bS&&s.c)throw A.a(B.Z)},\nog:function og(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nbS:function bS(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=!1\n_.$ti=c},\ne3:function e3(){},\nal:function al(){},\ne1:function e1(a,b){this.a=a\nthis.b=b},\ncR:function cR(a,b){this.a=a\nthis.b=b},\nrd(a){return\"SAVEPOINT s\"+a},\nrb(a){return\"RELEASE s\"+a},\nrc(a){return\"ROLLBACK TO s\"+a},\njq:function jq(){},\nkq:function kq(){},\nlb:function lb(){},\nkk:function kk(){},\nju:function ju(){},\nhm:function hm(){},\njJ:function jJ(){},\ni2:function i2(){},\nlT:function lT(a,b){this.a=a\nthis.b=b},\nlY:function lY(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nlW:function lW(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nlX:function lX(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nlV:function lV(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nlU:function lU(a,b){this.a=a\nthis.b=b},\niE:function iE(){},\nfb:function fb(a,b,c,d,e,f,g,h,i){var _=this\n_.y=a\n_.z=null\n_.Q=b\n_.as=c\n_.at=d\n_.ax=e\n_.ay=f\n_.ch=g\n_.e=h\n_.a=i\n_.b=0\n_.d=_.c=!1},\nnn:function nn(a){this.a=a},\nno:function no(a){this.a=a},\nfQ:function fQ(){},\njz:function jz(a,b){this.a=a\nthis.b=b},\njy:function jy(a){this.a=a},\ni3:function i3(a,b){var _=this\n_.e=a\n_.a=b\n_.b=0\n_.d=_.c=!1},\neV:function eV(a,b,c){var _=this\n_.e=a\n_.f=null\n_.r=b\n_.a=c\n_.b=0\n_.d=_.c=!1},\nmg:function mg(a,b){this.a=a\nthis.b=b},\nq9(a,b){var s,r,q,p=A.a3(t.N,t.S)\nfor(s=a.length,r=0;r<a.length;a.length===s||(0,A.W)(a),++r){q=a[r]\np.q(0,q,B.c.d0(a,q))}return new A.d6(a,b,p)},\nuA(a){var s,r,q,p,o,n,m,l,k\nif(a.length===0)return A.q9(B.r,B.aQ)\ns=J.iU(B.c.gG(a).ga_())\nr=A.d([],t.gP)\nfor(q=a.length,p=0;p<a.length;a.length===q||(0,A.W)(a),++p){o=a[p]\nn=[]\nfor(m=s.length,l=J.V(o),k=0;k<s.length;s.length===m||(0,A.W)(s),++k)n.push(l.i(o,s[k]))\nr.push(n)}return A.q9(s,r)},\nd6:function d6(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nks:function ks(a){this.a=a},\ntK(a,b){return new A.dx(a,b)},\nkr:function kr(){},\ndx:function dx(a,b){this.a=a\nthis.b=b},\nik:function ik(a,b){this.a=a\nthis.b=b},\net:function et(a,b){this.a=a\nthis.b=b},\ncu:function cu(a,b){this.a=a\nthis.b=b},\ney:function ey(){},\nf9:function f9(a){this.a=a},\nko:function ko(a){this.b=a},\ntX(a){var s=\"moor_contains\"\na.a6(B.q,!0,A.rH(),\"power\")\na.a6(B.q,!0,A.rH(),\"pow\")\na.a6(B.l,!0,A.dQ(A.xo()),\"sqrt\")\na.a6(B.l,!0,A.dQ(A.xn()),\"sin\")\na.a6(B.l,!0,A.dQ(A.xl()),\"cos\")\na.a6(B.l,!0,A.dQ(A.xp()),\"tan\")\na.a6(B.l,!0,A.dQ(A.xj()),\"asin\")\na.a6(B.l,!0,A.dQ(A.xi()),\"acos\")\na.a6(B.l,!0,A.dQ(A.xk()),\"atan\")\na.a6(B.q,!0,A.rI(),\"regexp\")\na.a6(B.Y,!0,A.rI(),\"regexp_moor_ffi\")\na.a6(B.q,!0,A.rG(),s)\na.a6(B.Y,!0,A.rG(),s)\na.fY(B.an,!0,!1,new A.jK(),\"current_time_millis\")},\nwe(a){var s=a.i(0,0),r=a.i(0,1)\nif(s==null||r==null||typeof s!=\"number\"||typeof r!=\"number\")return null\nreturn Math.pow(s,r)},\ndQ(a){return new A.nX(a)},\nwh(a){var s,r,q,p,o,n,m,l,k=!1,j=!0,i=!1,h=!1,g=a.a.b\nif(g<2||g>3)throw A.a(\"Expected two or three arguments to regexp\")\ns=a.i(0,0)\nq=a.i(0,1)\nif(s==null||q==null)return null\nif(typeof s!=\"string\"||typeof q!=\"string\")throw A.a(\"Expected two strings as parameters to regexp\")\nif(g===3){p=a.i(0,2)\nif(A.bn(p)){k=(p&1)===1\nj=(p&2)!==2\ni=(p&4)===4\nh=(p&8)===8}}r=null\ntry{o=k\nn=j\nm=i\nr=A.J(s,n,h,o,m)}catch(l){if(A.E(l) instanceof A.bs)throw A.a(\"Invalid regex\")\nelse throw l}o=r.b\nreturn o.test(q)},\nvO(a){var s,r,q=a.a.b\nif(q<2||q>3)throw A.a(\"Expected 2 or 3 arguments to moor_contains\")\ns=a.i(0,0)\nr=a.i(0,1)\nif(typeof s!=\"string\"||typeof r!=\"string\")throw A.a(\"First two args to contains must be strings\")\nreturn q===3&&a.i(0,2)===1?J.pz(s,r):B.a.M(s.toLowerCase(),r.toLowerCase())},\njK:function jK(){},\nnX:function nX(a){this.a=a},\nhc:function hc(a){var _=this\n_.a=$\n_.b=!1\n_.d=null\n_.e=a},\nkc:function kc(a,b){this.a=a\nthis.b=b},\nkd:function kd(a,b){this.a=a\nthis.b=b},\nbh:function bh(){this.a=null},\nkg:function kg(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nkh:function kh(a,b){this.a=a\nthis.b=b},\nuP(a,b,c){var s=null,r=new A.hC(t.a7),q=t.X,p=A.eD(s,s,!1,q),o=A.eD(s,s,!1,q),n=A.pR(new A.an(o,A.t(o).h(\"an<1>\")),new A.dH(p),!0,q)\nr.a=n\nq=A.pR(new A.an(p,A.t(p).h(\"an<1>\")),new A.dH(o),!0,q)\nr.b=q\na.onmessage=A.bb(new A.lA(b,r,c))\nn=n.b\nn===$&&A.G()\nnew A.an(n,A.t(n).h(\"an<1>\")).eB(new A.lB(c,a),new A.lC(b,a))\nreturn q},\nlA:function lA(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nlB:function lB(a,b){this.a=a\nthis.b=b},\nlC:function lC(a,b){this.a=a\nthis.b=b},\njv:function jv(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=null},\njx:function jx(a){this.a=a},\njw:function jw(a,b){this.a=a\nthis.b=b},\nq8(a){var s\n$label0$0:{if(a<=0){s=B.u\nbreak $label0$0}if(1===a){s=B.aY\nbreak $label0$0}if(2===a){s=B.aZ\nbreak $label0$0}if(a>2){s=B.v\nbreak $label0$0}s=A.y(A.e_(null))}return s},\nq7(a){if(\"v\" in a)return A.q8(A.h(A.r(a.v)))\nelse return B.u},\noL(a){var s,r,q,p,o,n,m,l,k,j,i=A.ad(a.type),h=a.payload\n$label0$0:{if(\"Error\"===i){s=new A.dm(A.ad(t.m.a(h)))\nbreak $label0$0}if(\"ServeDriftDatabase\"===i){s=t.m\ns.a(h)\nr=A.q7(h)\nq=A.bm(A.ad(h.sqlite))\ns=s.a(h.port)\np=A.or(B.aT,A.ad(h.storage))\no=A.ad(h.database)\nn=t.A.a(h.initPort)\nm=r.c\nl=m<2||A.bJ(h.migrations)\ns=new A.dc(q,s,p,o,n,r,l,m<3||A.bJ(h.new_serialization))\nbreak $label0$0}if(\"StartFileSystemServer\"===i){s=new A.eB(t.m.a(h))\nbreak $label0$0}if(\"RequestCompatibilityCheck\"===i){s=new A.da(A.ad(h))\nbreak $label0$0}if(\"DedicatedWorkerCompatibilityResult\"===i){t.m.a(h)\nk=A.d([],t.L)\nif(\"existing\" in h)B.c.aJ(k,A.pL(t.c.a(h.existing)))\ns=A.bJ(h.supportsNestedWorkers)\nq=A.bJ(h.canAccessOpfs)\np=A.bJ(h.supportsSharedArrayBuffers)\no=A.bJ(h.supportsIndexedDb)\nn=A.bJ(h.indexedDbExists)\nm=A.bJ(h.opfsExists)\nm=new A.e9(s,q,p,o,k,A.q7(h),n,m)\ns=m\nbreak $label0$0}if(\"SharedWorkerCompatibilityResult\"===i){s=t.c\ns.a(h)\nj=B.c.b8(h,t.y)\nif(h.length>5){k=A.pL(s.a(h[5]))\nr=h.length>6?A.q8(A.h(h[6])):B.u}else{k=B.B\nr=B.u}s=j.a\nq=J.V(s)\np=j.$ti.y[1]\ns=new A.c5(p.a(q.i(s,0)),p.a(q.i(s,1)),p.a(q.i(s,2)),k,r,p.a(q.i(s,3)),p.a(q.i(s,4)))\nbreak $label0$0}if(\"DeleteDatabase\"===i){s=h==null?t.K.a(h):h\nt.c.a(s)\nq=$.ps().i(0,A.ad(s[0]))\nq.toString\ns=new A.fR(new A.ap(q,A.ad(s[1])))\nbreak $label0$0}s=A.y(A.K(\"Unknown type \"+i,null))}return s},\npL(a){var s,r,q=A.d([],t.L),p=B.c.b8(a,t.m),o=p.$ti\np=new A.aZ(p,p.gl(0),o.h(\"aZ<z.E>\"))\no=o.h(\"z.E\")\nfor(;p.k();){s=p.d\nif(s==null)s=o.a(s)\nr=$.ps().i(0,A.ad(s.l))\nr.toString\nq.push(new A.ap(r,A.ad(s.n)))}return q},\npK(a){var s,r,q,p,o=A.d([],t.W)\nfor(s=a.length,r=0;r<a.length;a.length===s||(0,A.W)(a),++r){q=a[r]\np={}\np.l=q.a.b\np.n=q.b\no.push(p)}return o},\ndN(a,b,c,d){var s={}\ns.type=b\ns.payload=c\na.$2(s,d)},\nd5:function d5(a,b,c){this.c=a\nthis.a=b\nthis.b=c},\nlo:function lo(){},\nlr:function lr(a){this.a=a},\nlq:function lq(a){this.a=a},\nlp:function lp(a){this.a=a},\njb:function jb(){},\nc5:function c5(a,b,c,d,e,f,g){var _=this\n_.e=a\n_.f=b\n_.r=c\n_.a=d\n_.b=e\n_.c=f\n_.d=g},\ndm:function dm(a){this.a=a},\ndc:function dc(a,b,c,d,e,f,g,h){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f\n_.r=g\n_.w=h},\nda:function da(a){this.a=a},\ne9:function e9(a,b,c,d,e,f,g,h){var _=this\n_.e=a\n_.f=b\n_.r=c\n_.w=d\n_.a=e\n_.b=f\n_.c=g\n_.d=h},\neB:function eB(a){this.a=a},\nfR:function fR(a){this.a=a},\npb(){var s=self.navigator\nif(\"storage\" in s)return s.storage\nreturn null},\ncN(){var s=0,r=A.o(t.y),q,p=2,o,n=[],m,l,k,j,i,h,g,f\nvar $async$cN=A.p(function(a,b){if(a===1){o=b\ns=p}while(true)switch(s){case 0:g=A.pb()\nif(g==null){q=!1\ns=1\nbreak}m=null\nl=null\nk=null\np=4\ni=t.m\ns=7\nreturn A.c(A.a_(g.getDirectory(),i),$async$cN)\ncase 7:m=b\ns=8\nreturn A.c(A.a_(m.getFileHandle(\"_drift_feature_detection\",{create:!0}),i),$async$cN)\ncase 8:l=b\ns=9\nreturn A.c(A.a_(l.createSyncAccessHandle(),i),$async$cN)\ncase 9:k=b\nj=A.ha(k,\"getSize\",null,null,null,null)\ns=typeof j===\"object\"?10:11\nbreak\ncase 10:s=12\nreturn A.c(A.a_(i.a(j),t.X),$async$cN)\ncase 12:q=!1\nn=[1]\ns=5\nbreak\ncase 11:q=!0\nn=[1]\ns=5\nbreak\nn.push(6)\ns=5\nbreak\ncase 4:p=3\nf=o\nq=!1\nn=[1]\ns=5\nbreak\nn.push(6)\ns=5\nbreak\ncase 3:n=[2]\ncase 5:p=2\nif(k!=null)k.close()\ns=m!=null&&l!=null?13:14\nbreak\ncase 13:s=15\nreturn A.c(A.a_(m.removeEntry(\"_drift_feature_detection\"),t.X),$async$cN)\ncase 15:case 14:s=n.pop()\nbreak\ncase 6:case 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$cN,r)},\niN(){var s=0,r=A.o(t.y),q,p=2,o,n,m,l,k,j,i\nvar $async$iN=A.p(function(a,b){if(a===1){o=b\ns=p}while(true)switch(s){case 0:k=t.m\nj=k.a(self)\nif(!(\"indexedDB\" in j)||!(\"FileReader\" in j)){q=!1\ns=1\nbreak}n=k.a(j.indexedDB)\np=4\ns=7\nreturn A.c(A.jc(n.open(\"drift_mock_db\"),k),$async$iN)\ncase 7:m=b\nm.close()\nn.deleteDatabase(\"drift_mock_db\")\np=2\ns=6\nbreak\ncase 4:p=3\ni=o\nq=!1\ns=1\nbreak\ns=6\nbreak\ncase 3:s=2\nbreak\ncase 6:q=!0\ns=1\nbreak\ncase 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$iN,r)},\ndU(a){return A.wS(a)},\nwS(a){var s=0,r=A.o(t.y),q,p=2,o,n,m,l,k,j,i,h,g,f\nvar $async$dU=A.p(function(b,c){if(b===1){o=c\ns=p}while(true)$async$outer:switch(s){case 0:g={}\ng.a=null\np=4\ni=t.m\nn=i.a(i.a(self).indexedDB)\ns=\"databases\" in n?7:8\nbreak\ncase 7:s=9\nreturn A.c(A.a_(n.databases(),t.c),$async$dU)\ncase 9:m=c\ni=m\ni=J.M(t.cl.b(i)?i:new A.ah(i,A.Q(i).h(\"ah<1,A>\")))\nfor(;i.k();){l=i.gm()\nif(J.X(l.name,a)){q=!0\ns=1\nbreak $async$outer}}q=!1\ns=1\nbreak\ncase 8:k=n.open(a,1)\nk.onupgradeneeded=A.bb(new A.o_(g,k))\ns=10\nreturn A.c(A.jc(k,i),$async$dU)\ncase 10:j=c\nif(g.a==null)g.a=!0\nj.close()\ns=g.a===!1?11:12\nbreak\ncase 11:s=13\nreturn A.c(A.jc(n.deleteDatabase(a),t.X),$async$dU)\ncase 13:case 12:p=2\ns=6\nbreak\ncase 4:p=3\nf=o\ns=6\nbreak\ncase 3:s=2\nbreak\ncase 6:i=g.a\nq=i===!0\ns=1\nbreak\ncase 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$dU,r)},\no2(a){var s=0,r=A.o(t.H),q,p\nvar $async$o2=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:q=t.m\np=q.a(self)\ns=\"indexedDB\" in p?2:3\nbreak\ncase 2:s=4\nreturn A.c(A.jc(q.a(p.indexedDB).deleteDatabase(a),t.X),$async$o2)\ncase 4:case 3:return A.m(null,r)}})\nreturn A.n($async$o2,r)},\ndW(){var s=0,r=A.o(t.o),q,p=2,o,n=[],m,l,k,j,i,h,g,f,e\nvar $async$dW=A.p(function(a,b){if(a===1){o=b\ns=p}while(true)switch(s){case 0:f=A.pb()\nif(f==null){q=B.r\ns=1\nbreak}i=t.m\ns=3\nreturn A.c(A.a_(f.getDirectory(),i),$async$dW)\ncase 3:m=b\np=5\ns=8\nreturn A.c(A.a_(m.getDirectoryHandle(\"drift_db\"),i),$async$dW)\ncase 8:m=b\np=2\ns=7\nbreak\ncase 5:p=4\ne=o\nq=B.r\ns=1\nbreak\ns=7\nbreak\ncase 4:s=2\nbreak\ncase 7:i=m\ng=t.cO\nif(!(self.Symbol.asyncIterator in i))A.y(A.K(\"Target object does not implement the async iterable interface\",null))\nl=new A.f0(new A.od(),new A.e0(i,g),g.h(\"f0<Y.T,A>\"))\nk=A.d([],t.s)\ni=new A.dG(A.aD(l,\"stream\",t.K))\np=9\ncase 12:s=14\nreturn A.c(i.k(),$async$dW)\ncase 14:if(!b){s=13\nbreak}j=i.gm()\nif(J.X(j.kind,\"directory\"))J.on(k,j.name)\ns=12\nbreak\ncase 13:n.push(11)\ns=10\nbreak\ncase 9:n=[2]\ncase 10:p=2\ns=15\nreturn A.c(i.J(),$async$dW)\ncase 15:s=n.pop()\nbreak\ncase 11:q=k\ns=1\nbreak\ncase 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$dW,r)},\nfr(a){return A.wX(a)},\nwX(a){var s=0,r=A.o(t.H),q,p=2,o,n,m,l,k,j\nvar $async$fr=A.p(function(b,c){if(b===1){o=c\ns=p}while(true)switch(s){case 0:k=A.pb()\nif(k==null){s=1\nbreak}m=t.m\ns=3\nreturn A.c(A.a_(k.getDirectory(),m),$async$fr)\ncase 3:n=c\np=5\ns=8\nreturn A.c(A.a_(n.getDirectoryHandle(\"drift_db\"),m),$async$fr)\ncase 8:n=c\ns=9\nreturn A.c(A.a_(n.removeEntry(a,{recursive:!0}),t.X),$async$fr)\ncase 9:p=2\ns=7\nbreak\ncase 5:p=4\nj=o\ns=7\nbreak\ncase 4:s=2\nbreak\ncase 7:case 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$fr,r)},\njc(a,b){var s=new A.k($.i,b.h(\"k<0>\")),r=new A.a8(s,b.h(\"a8<0>\"))\nA.aB(a,\"success\",new A.jf(r,a,b),!1)\nA.aB(a,\"error\",new A.jg(r,a),!1)\nA.aB(a,\"blocked\",new A.jh(r,a),!1)\nreturn s},\no_:function o_(a,b){this.a=a\nthis.b=b},\nod:function od(){},\nfU:function fU(a,b){this.a=a\nthis.b=b},\njI:function jI(a,b){this.a=a\nthis.b=b},\njF:function jF(a){this.a=a},\njE:function jE(a){this.a=a},\njG:function jG(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\njH:function jH(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nm5:function m5(a,b){this.a=a\nthis.b=b},\ndb:function db(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=0\n_.d=c},\nkA:function kA(a){this.a=a},\nlm:function lm(a,b){this.a=a\nthis.b=b},\njf:function jf(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\njg:function jg(a,b){this.a=a\nthis.b=b},\njh:function jh(a,b){this.a=a\nthis.b=b},\nkK:function kK(a,b){this.a=a\nthis.b=null\nthis.c=b},\nkP:function kP(a){this.a=a},\nkL:function kL(a,b){this.a=a\nthis.b=b},\nkO:function kO(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nkM:function kM(a){this.a=a},\nkN:function kN(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nc8:function c8(a,b){this.a=a\nthis.b=b},\nbH:function bH(a,b){this.a=a\nthis.b=b},\nhT:function hT(a,b,c,d,e){var _=this\n_.e=a\n_.f=null\n_.r=b\n_.w=c\n_.x=d\n_.a=e\n_.b=0\n_.d=_.c=!1},\nnH:function nH(a,b,c,d,e,f,g){var _=this\n_.Q=a\n_.as=b\n_.at=c\n_.b=null\n_.d=_.c=!1\n_.e=d\n_.f=e\n_.r=f\n_.x=g\n_.y=$\n_.a=!1},\njl(a,b){if(a==null)a=\".\"\nreturn new A.fM(b,a)},\npa(a){return a},\nrs(a,b){var s,r,q,p,o,n,m,l\nfor(s=b.length,r=1;r<s;++r){if(b[r]==null||b[r-1]!=null)continue\nfor(;s>=1;s=q){q=s-1\nif(b[q]!=null)break}p=new A.av(\"\")\no=\"\"+(a+\"(\")\np.a=o\nn=A.Q(b)\nm=n.h(\"cw<1>\")\nl=new A.cw(b,0,s,m)\nl.hN(b,0,s,n.c)\nm=o+new A.D(l,new A.nY(),m.h(\"D<P.E,j>\")).aq(0,\", \")\np.a=m\np.a=m+(\"): part \"+(r-1)+\" was null, but part \"+r+\" was not.\")\nthrow A.a(A.K(p.j(0),null))}},\nfM:function fM(a,b){this.a=a\nthis.b=b},\njm:function jm(){},\njn:function jn(){},\nnY:function nY(){},\ndB:function dB(a){this.a=a},\ndC:function dC(a){this.a=a},\nk7:function k7(){},\nd4(a,b){var s,r,q,p,o,n=b.hu(a)\nb.ab(a)\nif(n!=null)a=B.a.K(a,n.length)\ns=t.s\nr=A.d([],s)\nq=A.d([],s)\ns=a.length\nif(s!==0&&b.D(a.charCodeAt(0))){q.push(a[0])\np=1}else{q.push(\"\")\np=0}for(o=p;o<s;++o)if(b.D(a.charCodeAt(o))){r.push(B.a.n(a,p,o))\nq.push(a[o])\np=o+1}if(p<s){r.push(B.a.K(a,p))\nq.push(\"\")}return new A.km(b,n,r,q)},\nkm:function km(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.d=c\n_.e=d},\nq1(a){return new A.eu(a)},\neu:function eu(a){this.a=a},\nuE(){if(A.eF().gY()!==\"file\")return $.cP()\nif(!B.a.ek(A.eF().gac(),\"/\"))return $.cP()\nif(A.aj(null,\"a/b\",null,null).eL()===\"a\\\\b\")return $.fu()\nreturn $.rT()},\nl1:function l1(){},\nkn:function kn(a,b,c){this.d=a\nthis.e=b\nthis.f=c},\nlk:function lk(a,b,c,d){var _=this\n_.d=a\n_.e=b\n_.f=c\n_.r=d},\nlM:function lM(a,b,c,d){var _=this\n_.d=a\n_.e=b\n_.f=c\n_.r=d},\nlN:function lN(){},\nhA:function hA(a,b,c,d,e,f){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f},\nkS:function kS(){},\ncj:function cj(a){this.a=a},\nku:function ku(){},\nhB:function hB(a,b){this.a=a\nthis.b=b},\nkv:function kv(){},\nkx:function kx(){},\nkw:function kw(){},\nd8:function d8(){},\nd9:function d9(){},\nvQ(a,b,c){var s,r,q,p,o,n=new A.hQ(c,A.b_(c.b,null,!1,t.X))\ntry{A.vR(a,b.$1(n))}catch(r){s=A.E(r)\nq=B.i.a5(A.fX(s))\np=a.b\no=p.bw(q)\np.jT.call(null,a.c,o,q.length)\np.e.call(null,o)}finally{}},\nvR(a,b){var s,r,q,p,o\n$label0$0:{s=null\nif(b==null){a.b.y1.call(null,a.c)\nbreak $label0$0}if(A.bn(b)){r=A.qw(b).j(0)\na.b.y2.call(null,a.c,self.BigInt(r))\nbreak $label0$0}if(b instanceof A.a6){r=A.pB(b).j(0)\na.b.y2.call(null,a.c,self.BigInt(r))\nbreak $label0$0}if(typeof b==\"number\"){a.b.jQ.call(null,a.c,b)\nbreak $label0$0}if(A.bM(b)){r=A.qw(b?1:0).j(0)\na.b.y2.call(null,a.c,self.BigInt(r))\nbreak $label0$0}if(typeof b==\"string\"){q=B.i.a5(b)\np=a.b\no=p.bw(q)\nA.cM(p.jR,\"call\",[null,a.c,o,q.length,-1])\np.e.call(null,o)\nbreak $label0$0}if(t.I.b(b)){p=a.b\no=p.bw(b)\nr=J.ae(b)\nA.cM(p.jS,\"call\",[null,a.c,o,self.BigInt(r),-1])\np.e.call(null,o)\nbreak $label0$0}s=A.y(A.ag(b,\"result\",\"Unsupported type\"))}return s},\nh_:function h_(a,b,c){this.b=a\nthis.c=b\nthis.d=c},\njr:function jr(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=!1},\njt:function jt(a){this.a=a},\njs:function js(a,b){this.a=a\nthis.b=b},\nhQ:function hQ(a,b){this.a=a\nthis.b=b},\nbr:function br(){},\no4:function o4(){},\nkR:function kR(){},\ncX:function cX(a){this.b=a\nthis.c=!0\nthis.d=!1},\ndf:function df(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=null},\njo:function jo(){},\nhu:function hu(a,b,c){this.d=a\nthis.a=b\nthis.c=c},\nbk:function bk(a,b){this.a=a\nthis.b=b},\nnh:function nh(a){this.a=a\nthis.b=-1},\niu:function iu(){},\niv:function iv(){},\nix:function ix(){},\niy:function iy(){},\nkl:function kl(a,b){this.a=a\nthis.b=b},\ncT:function cT(){},\ncr:function cr(a){this.a=a},\ncz(a){return new A.aI(a)},\naI:function aI(a){this.a=a},\nez:function ez(a){this.a=a},\nbF:function bF(){},\nfI:function fI(){},\nfH:function fH(){},\nlx:function lx(a){this.b=a},\nln:function ln(a,b){this.a=a\nthis.b=b},\nlz:function lz(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\nly:function ly(a,b,c){this.b=a\nthis.c=b\nthis.d=c},\nc7:function c7(a,b){this.b=a\nthis.c=b},\nbG:function bG(a,b){this.a=a\nthis.b=b},\ndk:function dk(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\ne0:function e0(a,b){this.a=a\nthis.$ti=b},\niW:function iW(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\niY:function iY(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\niX:function iX(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nbf(a,b){var s=new A.k($.i,b.h(\"k<0>\")),r=new A.a8(s,b.h(\"a8<0>\"))\nA.aB(a,\"success\",new A.jd(r,a,b),!1)\nA.aB(a,\"error\",new A.je(r,a),!1)\nreturn s},\ntU(a,b){var s=new A.k($.i,b.h(\"k<0>\")),r=new A.a8(s,b.h(\"a8<0>\"))\nA.aB(a,\"success\",new A.ji(r,a,b),!1)\nA.aB(a,\"error\",new A.jj(r,a),!1)\nA.aB(a,\"blocked\",new A.jk(r,a),!1)\nreturn s},\ncD:function cD(a,b){var _=this\n_.c=_.b=_.a=null\n_.d=a\n_.$ti=b},\nm6:function m6(a,b){this.a=a\nthis.b=b},\nm7:function m7(a,b){this.a=a\nthis.b=b},\njd:function jd(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nje:function je(a,b){this.a=a\nthis.b=b},\nji:function ji(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\njj:function jj(a,b){this.a=a\nthis.b=b},\njk:function jk(a,b){this.a=a\nthis.b=b},\nls(a,b){var s=0,r=A.o(t.g9),q,p,o,n,m,l\nvar $async$ls=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:l={}\nb.aa(0,new A.lu(l))\np=t.m\ns=3\nreturn A.c(A.a_(self.WebAssembly.instantiateStreaming(a,l),p),$async$ls)\ncase 3:o=d\nn=o.instance.exports\nif(\"_initialize\" in n)t.g.a(n._initialize).call()\nm=t.N\np=new A.hV(A.a3(m,t.g),A.a3(m,p))\np.hO(o.instance)\nq=p\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$ls,r)},\nhV:function hV(a,b){this.a=a\nthis.b=b},\nlu:function lu(a){this.a=a},\nlt:function lt(a){this.a=a},\nlw(a){var s=0,r=A.o(t.ab),q,p,o\nvar $async$lw=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:p=a.gh7()?new self.URL(a.j(0)):new self.URL(a.j(0),A.eF().j(0))\no=A\ns=3\nreturn A.c(A.a_(self.fetch(p,null),t.m),$async$lw)\ncase 3:q=o.lv(c)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$lw,r)},\nlv(a){var s=0,r=A.o(t.ab),q,p,o\nvar $async$lv=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:p=A\no=A\ns=3\nreturn A.c(A.ll(a),$async$lv)\ncase 3:q=new p.hW(new o.lx(c))\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$lv,r)},\nhW:function hW(a){this.a=a},\ndl:function dl(a,b,c,d,e){var _=this\n_.d=a\n_.e=b\n_.r=c\n_.b=d\n_.a=e},\nhU:function hU(a,b){this.a=a\nthis.b=b\nthis.c=0},\nqb(a){var s\nif(!J.X(a.byteLength,8))throw A.a(A.K(\"Must be 8 in length\",null))\ns=self.Int32Array\nreturn new A.kz(t.ha.a(A.dT(s,[a])))},\nuj(a){return B.h},\nuk(a){var s=a.b\nreturn new A.S(s.getInt32(0,!1),s.getInt32(4,!1),s.getInt32(8,!1))},\nul(a){var s=a.b\nreturn new A.aQ(B.j.cT(A.oF(a.a,16,s.getInt32(12,!1))),s.getInt32(0,!1),s.getInt32(4,!1),s.getInt32(8,!1))},\nkz:function kz(a){this.b=a},\nbi:function bi(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nac:function ac(a,b,c,d,e){var _=this\n_.c=a\n_.d=b\n_.a=c\n_.b=d\n_.$ti=e},\nbw:function bw(){},\naW:function aW(){},\nS:function S(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\naQ:function aQ(a,b,c,d){var _=this\n_.d=a\n_.a=b\n_.b=c\n_.c=d},\nhR(a){var s=0,r=A.o(t.ei),q,p,o,n,m,l,k,j,i\nvar $async$hR=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:k=t.m\ns=3\nreturn A.c(A.a_(A.rN().getDirectory(),k),$async$hR)\ncase 3:j=c\ni=$.fw().aQ(0,a.root)\np=i.length,o=0\ncase 4:if(!(o<i.length)){s=6\nbreak}s=7\nreturn A.c(A.a_(j.getDirectoryHandle(i[o],{create:!0}),k),$async$hR)\ncase 7:j=c\ncase 5:i.length===p||(0,A.W)(i),++o\ns=4\nbreak\ncase 6:k=t.cT\np=A.qb(a.synchronizationBuffer)\nn=a.communicationBuffer\nm=A.qe(n,65536,2048)\nl=self.Uint8Array\nq=new A.eG(p,new A.bi(n,m,t.Z.a(A.dT(l,[n]))),j,A.a3(t.S,k),A.oC(k))\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$hR,r)},\nit:function it(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\neG:function eG(a,b,c,d,e){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=0\n_.e=!1\n_.f=d\n_.r=e},\ndA:function dA(a,b,c,d,e,f,g){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f\n_.r=g\n_.w=!1\n_.x=null},\nh5(a){var s=0,r=A.o(t.bd),q,p,o,n,m,l\nvar $async$h5=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:p=t.N\no=new A.fE(a)\nn=A.ow(null)\nm=$.iP()\nl=new A.cY(o,n,new A.em(t.au),A.oC(p),A.a3(p,t.S),m,\"indexeddb\")\ns=3\nreturn A.c(o.d2(),$async$h5)\ncase 3:s=4\nreturn A.c(l.bQ(),$async$h5)\ncase 4:q=l\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$h5,r)},\nfE:function fE(a){this.a=null\nthis.b=a},\nj1:function j1(a){this.a=a},\niZ:function iZ(a){this.a=a},\nj2:function j2(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\nj0:function j0(a,b){this.a=a\nthis.b=b},\nj_:function j_(a,b){this.a=a\nthis.b=b},\nmh:function mh(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nmi:function mi(a,b){this.a=a\nthis.b=b},\niq:function iq(a,b){this.a=a\nthis.b=b},\ncY:function cY(a,b,c,d,e,f,g){var _=this\n_.d=a\n_.e=!1\n_.f=null\n_.r=b\n_.w=c\n_.x=d\n_.y=e\n_.b=f\n_.a=g},\nk2:function k2(a){this.a=a},\nij:function ij(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nmw:function mw(a,b){this.a=a\nthis.b=b},\nao:function ao(){},\ndt:function dt(a,b){var _=this\n_.w=a\n_.d=b\n_.c=_.b=_.a=null},\ndr:function dr(a,b,c){var _=this\n_.w=a\n_.x=b\n_.d=c\n_.c=_.b=_.a=null},\ncC:function cC(a,b,c){var _=this\n_.w=a\n_.x=b\n_.d=c\n_.c=_.b=_.a=null},\ncK:function cK(a,b,c,d,e){var _=this\n_.w=a\n_.x=b\n_.y=c\n_.z=d\n_.d=e\n_.c=_.b=_.a=null},\now(a){var s=$.iP()\nreturn new A.h2(A.a3(t.N,t.aD),s,\"dart-memory\")},\nh2:function h2(a,b,c){this.d=a\nthis.b=b\nthis.a=c},\nii:function ii(a,b,c){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=0},\nhx(a){var s=0,r=A.o(t.gW),q,p,o,n,m,l,k\nvar $async$hx=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:k=A.rN()\nif(k==null)throw A.a(A.cz(1))\np=t.m\ns=3\nreturn A.c(A.a_(k.getDirectory(),p),$async$hx)\ncase 3:o=c\nn=$.iQ().aQ(0,a),m=n.length,l=0\ncase 4:if(!(l<n.length)){s=6\nbreak}s=7\nreturn A.c(A.a_(o.getDirectoryHandle(n[l],{create:!0}),p),$async$hx)\ncase 7:o=c\ncase 5:n.length===m||(0,A.W)(n),++l\ns=4\nbreak\ncase 6:q=A.hw(o,\"simple-opfs\")\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$hx,r)},\nhw(a,b){var s=0,r=A.o(t.gW),q,p,o,n,m,l,k,j,i,h,g\nvar $async$hw=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:j=new A.kQ(a)\ns=3\nreturn A.c(j.$1(\"meta\"),$async$hw)\ncase 3:i=d\ni.truncate(2)\np=A.a3(t.ez,t.m)\no=0\ncase 4:if(!(o<2)){s=6\nbreak}n=B.a9[o]\nh=p\ng=n\ns=7\nreturn A.c(j.$1(n.b),$async$hw)\ncase 7:h.q(0,g,d)\ncase 5:++o\ns=4\nbreak\ncase 6:m=new Uint8Array(2)\nl=A.ow(null)\nk=$.iP()\nq=new A.de(i,m,p,l,k,b)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$hw,r)},\ncW:function cW(a,b,c){this.c=a\nthis.a=b\nthis.b=c},\nde:function de(a,b,c,d,e,f){var _=this\n_.d=a\n_.e=b\n_.f=c\n_.r=d\n_.b=e\n_.a=f},\nkQ:function kQ(a){this.a=a},\niz:function iz(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=0},\nll(d6){var s=0,r=A.o(t.h2),q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,d0,d1,d2,d3,d4,d5\nvar $async$ll=A.p(function(d7,d8){if(d7===1)return A.l(d8,r)\nwhile(true)switch(s){case 0:d4=A.v2()\nd5=d4.b\nd5===$&&A.G()\ns=3\nreturn A.c(A.ls(d6,d5),$async$ll)\ncase 3:p=d8\nd5=d4.c\nd5===$&&A.G()\no=p.a\nn=o.i(0,\"dart_sqlite3_malloc\")\nn.toString\nm=o.i(0,\"dart_sqlite3_free\")\nm.toString\nl=o.i(0,\"dart_sqlite3_create_scalar_function\")\nl.toString\nk=o.i(0,\"dart_sqlite3_create_aggregate_function\")\nk.toString\no.i(0,\"dart_sqlite3_create_window_function\").toString\no.i(0,\"dart_sqlite3_create_collation\").toString\nj=o.i(0,\"dart_sqlite3_register_vfs\")\nj.toString\no.i(0,\"sqlite3_vfs_unregister\").toString\ni=o.i(0,\"dart_sqlite3_updates\")\ni.toString\no.i(0,\"sqlite3_libversion\").toString\no.i(0,\"sqlite3_sourceid\").toString\no.i(0,\"sqlite3_libversion_number\").toString\nh=o.i(0,\"sqlite3_open_v2\")\nh.toString\ng=o.i(0,\"sqlite3_close_v2\")\ng.toString\nf=o.i(0,\"sqlite3_extended_errcode\")\nf.toString\ne=o.i(0,\"sqlite3_errmsg\")\ne.toString\nd=o.i(0,\"sqlite3_errstr\")\nd.toString\nc=o.i(0,\"sqlite3_extended_result_codes\")\nc.toString\nb=o.i(0,\"sqlite3_exec\")\nb.toString\no.i(0,\"sqlite3_free\").toString\na=o.i(0,\"sqlite3_prepare_v3\")\na.toString\na0=o.i(0,\"sqlite3_bind_parameter_count\")\na0.toString\na1=o.i(0,\"sqlite3_column_count\")\na1.toString\na2=o.i(0,\"sqlite3_column_name\")\na2.toString\na3=o.i(0,\"sqlite3_reset\")\na3.toString\na4=o.i(0,\"sqlite3_step\")\na4.toString\na5=o.i(0,\"sqlite3_finalize\")\na5.toString\na6=o.i(0,\"sqlite3_column_type\")\na6.toString\na7=o.i(0,\"sqlite3_column_int64\")\na7.toString\na8=o.i(0,\"sqlite3_column_double\")\na8.toString\na9=o.i(0,\"sqlite3_column_bytes\")\na9.toString\nb0=o.i(0,\"sqlite3_column_blob\")\nb0.toString\nb1=o.i(0,\"sqlite3_column_text\")\nb1.toString\nb2=o.i(0,\"sqlite3_bind_null\")\nb2.toString\nb3=o.i(0,\"sqlite3_bind_int64\")\nb3.toString\nb4=o.i(0,\"sqlite3_bind_double\")\nb4.toString\nb5=o.i(0,\"sqlite3_bind_text\")\nb5.toString\nb6=o.i(0,\"sqlite3_bind_blob64\")\nb6.toString\nb7=o.i(0,\"sqlite3_bind_parameter_index\")\nb7.toString\nb8=o.i(0,\"sqlite3_changes\")\nb8.toString\nb9=o.i(0,\"sqlite3_last_insert_rowid\")\nb9.toString\nc0=o.i(0,\"sqlite3_user_data\")\nc0.toString\nc1=o.i(0,\"sqlite3_result_null\")\nc1.toString\nc2=o.i(0,\"sqlite3_result_int64\")\nc2.toString\nc3=o.i(0,\"sqlite3_result_double\")\nc3.toString\nc4=o.i(0,\"sqlite3_result_text\")\nc4.toString\nc5=o.i(0,\"sqlite3_result_blob64\")\nc5.toString\nc6=o.i(0,\"sqlite3_result_error\")\nc6.toString\nc7=o.i(0,\"sqlite3_value_type\")\nc7.toString\nc8=o.i(0,\"sqlite3_value_int64\")\nc8.toString\nc9=o.i(0,\"sqlite3_value_double\")\nc9.toString\nd0=o.i(0,\"sqlite3_value_bytes\")\nd0.toString\nd1=o.i(0,\"sqlite3_value_text\")\nd1.toString\nd2=o.i(0,\"sqlite3_value_blob\")\nd2.toString\no.i(0,\"sqlite3_aggregate_context\").toString\no.i(0,\"sqlite3_get_autocommit\").toString\nd3=o.i(0,\"sqlite3_stmt_isexplain\")\nd3.toString\no.i(0,\"sqlite3_stmt_readonly\").toString\no.i(0,\"dart_sqlite3_db_config_int\")\np.b.i(0,\"sqlite3_temp_directory\").toString\nq=d4.a=new A.hS(d5,d4.d,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1,a2,a3,a4,a6,a7,a8,a9,b1,b0,b2,b3,b4,b5,b6,b7,a5,b8,b9,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,d0,d1,d2,d3)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$ll,r)},\naL(a){var s,r,q\ntry{a.$0()\nreturn 0}catch(r){q=A.E(r)\nif(q instanceof A.aI){s=q\nreturn s.a}else return 1}},\noN(a,b){var s,r=A.bj(a.buffer,b,null)\nfor(s=0;r[s]!==0;)++s\nreturn s},\nc9(a,b,c){var s=a.buffer\nreturn B.j.cT(A.bj(s,b,c==null?A.oN(a,b):c))},\noM(a,b,c){var s\nif(b===0)return null\ns=a.buffer\nreturn B.j.cT(A.bj(s,b,c==null?A.oN(a,b):c))},\nqv(a,b,c){var s=new Uint8Array(c)\nB.e.aD(s,0,A.bj(a.buffer,b,c))\nreturn s},\nv2(){var s=t.S\ns=new A.mx(new A.jp(A.a3(s,t.gy),A.a3(s,t.b9),A.a3(s,t.fL),A.a3(s,t.ga)))\ns.hP()\nreturn s},\nhS:function hS(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,d0){var _=this\n_.b=a\n_.c=b\n_.d=c\n_.e=d\n_.w=e\n_.x=f\n_.y=g\n_.Q=h\n_.ay=i\n_.ch=j\n_.CW=k\n_.cx=l\n_.cy=m\n_.db=n\n_.dx=o\n_.fr=p\n_.fx=q\n_.fy=r\n_.go=s\n_.id=a0\n_.k1=a1\n_.k2=a2\n_.k3=a3\n_.k4=a4\n_.ok=a5\n_.p1=a6\n_.p2=a7\n_.p3=a8\n_.p4=a9\n_.R8=b0\n_.RG=b1\n_.rx=b2\n_.ry=b3\n_.to=b4\n_.x1=b5\n_.x2=b6\n_.xr=b7\n_.y1=b8\n_.y2=b9\n_.jQ=c0\n_.jR=c1\n_.jS=c2\n_.jT=c3\n_.jU=c4\n_.jV=c5\n_.jW=c6\n_.h3=c7\n_.jX=c8\n_.jY=c9\n_.jZ=d0},\nmx:function mx(a){var _=this\n_.c=_.b=_.a=$\n_.d=a},\nmN:function mN(a){this.a=a},\nmO:function mO(a,b){this.a=a\nthis.b=b},\nmE:function mE(a,b,c,d,e,f,g){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e\n_.f=f\n_.r=g},\nmP:function mP(a,b){this.a=a\nthis.b=b},\nmD:function mD(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nn_:function n_(a,b){this.a=a\nthis.b=b},\nmC:function mC(a,b,c,d,e){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e},\nn5:function n5(a,b){this.a=a\nthis.b=b},\nmB:function mB(a,b,c,d,e){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e},\nn6:function n6(a,b){this.a=a\nthis.b=b},\nmM:function mM(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\nn7:function n7(a){this.a=a},\nmL:function mL(a,b){this.a=a\nthis.b=b},\nn8:function n8(a,b){this.a=a\nthis.b=b},\nn9:function n9(a){this.a=a},\nna:function na(a){this.a=a},\nmK:function mK(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nnb:function nb(a,b){this.a=a\nthis.b=b},\nmJ:function mJ(a,b,c,d,e){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e},\nmQ:function mQ(a,b){this.a=a\nthis.b=b},\nmI:function mI(a,b,c,d,e){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d\n_.e=e},\nmR:function mR(a){this.a=a},\nmH:function mH(a,b){this.a=a\nthis.b=b},\nmS:function mS(a){this.a=a},\nmG:function mG(a,b){this.a=a\nthis.b=b},\nmT:function mT(a,b){this.a=a\nthis.b=b},\nmF:function mF(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nmU:function mU(a){this.a=a},\nmA:function mA(a,b){this.a=a\nthis.b=b},\nmV:function mV(a){this.a=a},\nmz:function mz(a,b){this.a=a\nthis.b=b},\nmW:function mW(a,b){this.a=a\nthis.b=b},\nmy:function my(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\nmX:function mX(a){this.a=a},\nmY:function mY(a){this.a=a},\nmZ:function mZ(a){this.a=a},\nn0:function n0(a){this.a=a},\nn1:function n1(a){this.a=a},\nn2:function n2(a){this.a=a},\nn3:function n3(a,b){this.a=a\nthis.b=b},\nn4:function n4(a,b){this.a=a\nthis.b=b},\njp:function jp(a,b,c,d){var _=this\n_.a=0\n_.b=a\n_.d=b\n_.e=c\n_.f=d\n_.r=null},\nht:function ht(a,b,c){this.a=a\nthis.b=b\nthis.c=c},\ntO(a){var s,r,q=u.q\nif(a.length===0)return new A.be(A.aG(A.d([],t.J),t.a))\ns=$.pw()\nif(B.a.M(a,s)){s=B.a.aQ(a,s)\nr=A.Q(s)\nreturn new A.be(A.aG(new A.az(new A.aT(s,new A.j3(),r.h(\"aT<1>\")),A.xE(),r.h(\"az<1,a1>\")),t.a))}if(!B.a.M(a,q))return new A.be(A.aG(A.d([A.qn(a)],t.J),t.a))\nreturn new A.be(A.aG(new A.D(A.d(a.split(q),t.s),A.xD(),t.fe),t.a))},\nbe:function be(a){this.a=a},\nj3:function j3(){},\nj8:function j8(){},\nj7:function j7(){},\nj5:function j5(){},\nj6:function j6(a){this.a=a},\nj4:function j4(a){this.a=a},\nu7(a){return A.pO(a)},\npO(a){return A.h0(a,new A.jU(a))},\nu6(a){return A.u3(a)},\nu3(a){return A.h0(a,new A.jS(a))},\nu0(a){return A.h0(a,new A.jP(a))},\nu4(a){return A.u1(a)},\nu1(a){return A.h0(a,new A.jQ(a))},\nu5(a){return A.u2(a)},\nu2(a){return A.h0(a,new A.jR(a))},\nh1(a){if(B.a.M(a,$.rQ()))return A.bm(a)\nelse if(B.a.M(a,$.rR()))return A.qU(a,!0)\nelse if(B.a.u(a,\"/\"))return A.qU(a,!1)\nif(B.a.M(a,\"\\\\\"))return $.ty().hp(a)\nreturn A.bm(a)},\nh0(a,b){var s,r\ntry{s=b.$0()\nreturn s}catch(r){if(A.E(r) instanceof A.bs)return new A.bl(A.aj(null,\"unparsed\",null,null),a)\nelse throw r}},\nN:function N(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.d=d},\njU:function jU(a){this.a=a},\njS:function jS(a){this.a=a},\njT:function jT(a){this.a=a},\njP:function jP(a){this.a=a},\njQ:function jQ(a){this.a=a},\njR:function jR(a){this.a=a},\nhd:function hd(a){this.a=a\nthis.b=$},\nqm(a){if(t.a.b(a))return a\nif(a instanceof A.be)return a.ho()\nreturn new A.hd(new A.l7(a))},\nqn(a){var s,r,q\ntry{if(a.length===0){r=A.qj(A.d([],t.e),null)\nreturn r}if(B.a.M(a,$.tr())){r=A.uH(a)\nreturn r}if(B.a.M(a,\"\\tat \")){r=A.uG(a)\nreturn r}if(B.a.M(a,$.th())||B.a.M(a,$.tf())){r=A.uF(a)\nreturn r}if(B.a.M(a,u.q)){r=A.tO(a).ho()\nreturn r}if(B.a.M(a,$.tk())){r=A.qk(a)\nreturn r}r=A.ql(a)\nreturn r}catch(q){r=A.E(q)\nif(r instanceof A.bs){s=r\nthrow A.a(A.ai(s.a+\"\\nStack trace:\\n\"+a,null,null))}else throw q}},\nuJ(a){return A.ql(a)},\nql(a){var s=A.aG(A.uK(a),t.B)\nreturn new A.a1(s)},\nuK(a){var s,r=B.a.eM(a),q=$.pw(),p=t.U,o=new A.aT(A.d(A.bc(r,q,\"\").split(\"\\n\"),t.s),new A.l8(),p)\nif(!o.gt(0).k())return A.d([],t.e)\nr=A.oJ(o,o.gl(0)-1,p.h(\"f.E\"))\nr=A.en(r,A.x2(),A.t(r).h(\"f.E\"),t.B)\ns=A.ay(r,!0,A.t(r).h(\"f.E\"))\nif(!J.tC(o.gC(0),\".da\"))B.c.v(s,A.pO(o.gC(0)))\nreturn s},\nuH(a){var s=A.b3(A.d(a.split(\"\\n\"),t.s),1,null,t.N).hF(0,new A.l6()),r=t.B\nr=A.aG(A.en(s,A.rA(),s.$ti.h(\"f.E\"),r),r)\nreturn new A.a1(r)},\nuG(a){var s=A.aG(new A.az(new A.aT(A.d(a.split(\"\\n\"),t.s),new A.l5(),t.U),A.rA(),t.M),t.B)\nreturn new A.a1(s)},\nuF(a){var s=A.aG(new A.az(new A.aT(A.d(B.a.eM(a).split(\"\\n\"),t.s),new A.l3(),t.U),A.x0(),t.M),t.B)\nreturn new A.a1(s)},\nuI(a){return A.qk(a)},\nqk(a){var s=a.length===0?A.d([],t.e):new A.az(new A.aT(A.d(B.a.eM(a).split(\"\\n\"),t.s),new A.l4(),t.U),A.x1(),t.M)\ns=A.aG(s,t.B)\nreturn new A.a1(s)},\nqj(a,b){var s=A.aG(a,t.B)\nreturn new A.a1(s)},\na1:function a1(a){this.a=a},\nl7:function l7(a){this.a=a},\nl8:function l8(){},\nl6:function l6(){},\nl5:function l5(){},\nl3:function l3(){},\nl4:function l4(){},\nla:function la(){},\nl9:function l9(a){this.a=a},\nbl:function bl(a,b){this.a=a\nthis.w=b},\ne5:function e5(a){var _=this\n_.b=_.a=$\n_.c=null\n_.d=!1\n_.$ti=a},\neP:function eP(a,b,c){this.a=a\nthis.b=b\nthis.$ti=c},\neO:function eO(a,b){this.b=a\nthis.a=b},\npR(a,b,c,d){var s,r={}\nr.a=a\ns=new A.ef(d.h(\"ef<0>\"))\ns.hL(b,!0,r,d)\nreturn s},\nef:function ef(a){var _=this\n_.b=_.a=$\n_.c=null\n_.d=!1\n_.$ti=a},\nk0:function k0(a,b){this.a=a\nthis.b=b},\nk_:function k_(a){this.a=a},\neY:function eY(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.e=_.d=!1\n_.r=_.f=null\n_.w=d},\nhC:function hC(a){this.b=this.a=$\nthis.$ti=a},\neC:function eC(){},\naB(a,b,c,d){var s\nif(c==null)s=null\nelse{s=A.rt(new A.me(c),t.m)\ns=s==null?null:A.bb(s)}s=new A.ic(a,b,s,!1)\ns.e3()\nreturn s},\nrt(a,b){var s=$.i\nif(s===B.d)return a\nreturn s.eg(a,b)},\nos:function os(a,b){this.a=a\nthis.$ti=b},\neU:function eU(a,b,c,d){var _=this\n_.a=a\n_.b=b\n_.c=c\n_.$ti=d},\nic:function ic(a,b,c,d){var _=this\n_.a=0\n_.b=a\n_.c=b\n_.d=c\n_.e=d},\nme:function me(a){this.a=a},\nmf:function mf(a){this.a=a},\npn(a){if(typeof dartPrint==\"function\"){dartPrint(a)\nreturn}if(typeof console==\"object\"&&typeof console.log!=\"undefined\"){console.log(a)\nreturn}if(typeof print==\"function\"){print(a)\nreturn}throw\"Unable to print message: \"+String(a)},\nui(a){return a},\noy(a,b){var s,r,q,p,o,n\nif(b.length===0)return!1\ns=b.split(\".\")\nr=t.m.a(self)\nfor(q=s.length,p=t.A,o=0;o<q;++o){n=s[o]\nr=p.a(r[n])\nif(r==null)return!1}return a instanceof t.g.a(r)},\nha(a,b,c,d,e,f){var s\nif(c==null)return a[b]()\nelse if(d==null)return a[b](c)\nelse if(e==null)return a[b](c,d)\nelse{s=a[b](c,d,e)\nreturn s}},\npf(){var s,r,q,p,o=null\ntry{o=A.eF()}catch(s){if(t.g8.b(A.E(s))){r=$.nQ\nif(r!=null)return r\nthrow s}else throw s}if(J.X(o,$.ra)){r=$.nQ\nr.toString\nreturn r}$.ra=o\nif($.pr()===$.cP())r=$.nQ=o.hm(\".\").j(0)\nelse{q=o.eL()\np=q.length-1\nr=$.nQ=p===0?q:B.a.n(q,0,p)}return r},\nrD(a){var s\nif(!(a>=65&&a<=90))s=a>=97&&a<=122\nelse s=!0\nreturn s},\nrz(a,b){var s,r,q=null,p=a.length,o=b+2\nif(p<o)return q\nif(!A.rD(a.charCodeAt(b)))return q\ns=b+1\nif(a.charCodeAt(s)!==58){r=b+4\nif(p<r)return q\nif(B.a.n(a,s,r).toLowerCase()!==\"%3a\")return q\nb=o}s=b+2\nif(p===s)return s\nif(a.charCodeAt(s)!==47)return q\nreturn b+3},\npe(a,b,c,d,e,f){var s=b.a,r=b.b,q=A.h(A.r(s.CW.call(null,r))),p=a.b\nreturn new A.hA(A.c9(s.b,A.h(A.r(s.cx.call(null,r))),null),A.c9(p.b,A.h(A.r(p.cy.call(null,q))),null)+\" (code \"+q+\")\",c,d,e,f)},\niO(a,b,c,d,e){throw A.a(A.pe(a.a,a.b,b,c,d,e))},\npB(a){if(a.ag(0,$.tw())<0||a.ag(0,$.tv())>0)throw A.a(A.jL(\"BigInt value exceeds the range of 64 bits\"))\nreturn a},\nky(a){var s=0,r=A.o(t.E),q\nvar $async$ky=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:s=3\nreturn A.c(A.a_(a.arrayBuffer(),t.bZ),$async$ky)\ncase 3:q=c\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$ky,r)},\nqe(a,b,c){var s=self.DataView,r=[a]\nr.push(b)\nr.push(c)\nreturn t.gT.a(A.dT(s,r))},\noF(a,b,c){var s=self.Uint8Array,r=[a]\nr.push(b)\nr.push(c)\nreturn t.Z.a(A.dT(s,r))},\ntL(a,b){self.Atomics.notify(a,b,1/0)},\nrN(){var s=self.navigator\nif(\"storage\" in s)return s.storage\nreturn null},\njM(a,b,c){return a.read(b,c)},\not(a,b,c){return a.write(b,c)},\npN(a,b){return A.a_(a.removeEntry(b,{recursive:!1}),t.X)},\nov(a,b){var s,r\nfor(s=b,r=0;r<16;++r)s+=A.aA(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012346789\".charCodeAt(a.hc(61)))\nreturn s.charCodeAt(0)==0?s:s},\nxg(){var s=t.m.a(self)\nif(A.oy(s,\"DedicatedWorkerGlobalScope\"))new A.jv(s,new A.bh(),new A.fU(A.a3(t.N,t.fE),null)).T()\nelse if(A.oy(s,\"SharedWorkerGlobalScope\"))new A.kK(s,new A.fU(A.a3(t.N,t.fE),null)).T()}},B={}\nvar w=[A,J,B]\nvar $={}\nA.oA.prototype={}\nJ.h7.prototype={\nO(a,b){return a===b},\ngB(a){return A.ev(a)},\nj(a){return\"Instance of '\"+A.kp(a)+\"'\"},\ngV(a){return A.bO(A.p8(this))}}\nJ.h8.prototype={\nj(a){return String(a)},\ngB(a){return a?519018:218159},\ngV(a){return A.bO(t.y)},\n$iL:1,\n$iU:1}\nJ.ej.prototype={\nO(a,b){return null==b},\nj(a){return\"null\"},\ngB(a){return 0},\n$iL:1,\n$iF:1}\nJ.ek.prototype={$iA:1}\nJ.bY.prototype={\ngB(a){return 0},\nj(a){return String(a)}}\nJ.hr.prototype={}\nJ.cy.prototype={}\nJ.bW.prototype={\nj(a){var s=a[$.dX()]\nif(s==null)return this.hG(a)\nreturn\"JavaScript function for \"+J.aU(s)}}\nJ.aY.prototype={\ngB(a){return 0},\nj(a){return String(a)}}\nJ.el.prototype={\ngB(a){return 0},\nj(a){return String(a)}}\nJ.w.prototype={\nb8(a,b){return new A.ah(a,A.Q(a).h(\"@<1>\").H(b).h(\"ah<1,2>\"))},\nv(a,b){if(!!a.fixed$length)A.y(A.H(\"add\"))\na.push(b)},\nd6(a,b){var s\nif(!!a.fixed$length)A.y(A.H(\"removeAt\"))\ns=a.length\nif(b>=s)throw A.a(A.kt(b,null))\nreturn a.splice(b,1)[0]},\ncY(a,b,c){var s\nif(!!a.fixed$length)A.y(A.H(\"insert\"))\ns=a.length\nif(b>s)throw A.a(A.kt(b,null))\na.splice(b,0,c)},\nev(a,b,c){var s,r\nif(!!a.fixed$length)A.y(A.H(\"insertAll\"))\nA.qa(b,0,a.length,\"index\")\nif(!t.Q.b(c))c=J.iU(c)\ns=J.ae(c)\na.length=a.length+s\nr=b+s\nthis.Z(a,r,a.length,a,b)\nthis.aj(a,b,r,c)},\nhi(a){if(!!a.fixed$length)A.y(A.H(\"removeLast\"))\nif(a.length===0)throw A.a(A.dV(a,-1))\nreturn a.pop()},\nA(a,b){var s\nif(!!a.fixed$length)A.y(A.H(\"remove\"))\nfor(s=0;s<a.length;++s)if(J.X(a[s],b)){a.splice(s,1)\nreturn!0}return!1},\naJ(a,b){var s\nif(!!a.fixed$length)A.y(A.H(\"addAll\"))\nif(Array.isArray(b)){this.hU(a,b)\nreturn}for(s=J.M(b);s.k();)a.push(s.gm())},\nhU(a,b){var s,r=b.length\nif(r===0)return\nif(a===b)throw A.a(A.ax(a))\nfor(s=0;s<r;++s)a.push(b[s])},\nc1(a){if(!!a.fixed$length)A.y(A.H(\"clear\"))\na.length=0},\naa(a,b){var s,r=a.length\nfor(s=0;s<r;++s){b.$1(a[s])\nif(a.length!==r)throw A.a(A.ax(a))}},\nbd(a,b,c){return new A.D(a,b,A.Q(a).h(\"@<1>\").H(c).h(\"D<1,2>\"))},\naq(a,b){var s,r=A.b_(a.length,\"\",!1,t.N)\nfor(s=0;s<a.length;++s)r[s]=A.u(a[s])\nreturn r.join(b)},\nc5(a){return this.aq(a,\"\")},\nah(a,b){return A.b3(a,0,A.aD(b,\"count\",t.S),A.Q(a).c)},\nX(a,b){return A.b3(a,b,null,A.Q(a).c)},\nN(a,b){return a[b]},\na0(a,b,c){var s=a.length\nif(b>s)throw A.a(A.a4(b,0,s,\"start\",null))\nif(c<b||c>s)throw A.a(A.a4(c,b,s,\"end\",null))\nif(b===c)return A.d([],A.Q(a))\nreturn A.d(a.slice(b,c),A.Q(a))},\nco(a,b,c){A.b9(b,c,a.length)\nreturn A.b3(a,b,c,A.Q(a).c)},\ngG(a){if(a.length>0)return a[0]\nthrow A.a(A.ak())},\ngC(a){var s=a.length\nif(s>0)return a[s-1]\nthrow A.a(A.ak())},\nZ(a,b,c,d,e){var s,r,q,p,o\nif(!!a.immutable$list)A.y(A.H(\"setRange\"))\nA.b9(b,c,a.length)\ns=c-b\nif(s===0)return\nA.ab(e,\"skipCount\")\nif(t.j.b(d)){r=d\nq=e}else{r=J.dZ(d,e).az(0,!1)\nq=0}p=J.V(r)\nif(q+s>p.gl(r))throw A.a(A.pT())\nif(q<b)for(o=s-1;o>=0;--o)a[b+o]=p.i(r,q+o)\nelse for(o=0;o<s;++o)a[b+o]=p.i(r,q+o)},\naj(a,b,c,d){return this.Z(a,b,c,d,0)},\nhC(a,b){var s,r,q,p,o\nif(!!a.immutable$list)A.y(A.H(\"sort\"))\ns=a.length\nif(s<2)return\nif(b==null)b=J.vZ()\nif(s===2){r=a[0]\nq=a[1]\nif(b.$2(r,q)>0){a[0]=q\na[1]=r}return}p=0\nif(A.Q(a).c.b(null))for(o=0;o<a.length;++o)if(a[o]===void 0){a[o]=null;++p}a.sort(A.cf(b,2))\nif(p>0)this.iW(a,p)},\nhB(a){return this.hC(a,null)},\niW(a,b){var s,r=a.length\nfor(;s=r-1,r>0;r=s)if(a[s]===null){a[s]=void 0;--b\nif(b===0)break}},\nd0(a,b){var s,r=a.length,q=r-1\nif(q<0)return-1\nq>=r\nfor(s=q;s>=0;--s)if(J.X(a[s],b))return s\nreturn-1},\ngF(a){return a.length===0},\nj(a){return A.ox(a,\"[\",\"]\")},\naz(a,b){var s=A.d(a.slice(0),A.Q(a))\nreturn s},\ncj(a){return this.az(a,!0)},\ngt(a){return new J.fz(a,a.length,A.Q(a).h(\"fz<1>\"))},\ngB(a){return A.ev(a)},\ngl(a){return a.length},\ni(a,b){if(!(b>=0&&b<a.length))throw A.a(A.dV(a,b))\nreturn a[b]},\nq(a,b,c){if(!!a.immutable$list)A.y(A.H(\"indexed set\"))\nif(!(b>=0&&b<a.length))throw A.a(A.dV(a,b))\na[b]=c},\n$iar:1,\n$iv:1,\n$if:1,\n$iq:1}\nJ.k9.prototype={}\nJ.fz.prototype={\ngm(){var s=this.d\nreturn s==null?this.$ti.c.a(s):s},\nk(){var s,r=this,q=r.a,p=q.length\nif(r.b!==p)throw A.a(A.W(q))\ns=r.c\nif(s>=p){r.d=null\nreturn!1}r.d=q[s]\nr.c=s+1\nreturn!0}}\nJ.cZ.prototype={\nag(a,b){var s\nif(a<b)return-1\nelse if(a>b)return 1\nelse if(a===b){if(a===0){s=this.gey(b)\nif(this.gey(a)===s)return 0\nif(this.gey(a))return-1\nreturn 1}return 0}else if(isNaN(a)){if(isNaN(b))return 0\nreturn 1}else return-1},\ngey(a){return a===0?1/a<0:a<0},\nkE(a){var s\nif(a>=-2147483648&&a<=2147483647)return a|0\nif(isFinite(a)){s=a<0?Math.ceil(a):Math.floor(a)\nreturn s+0}throw A.a(A.H(\"\"+a+\".toInt()\"))},\njE(a){var s,r\nif(a>=0){if(a<=2147483647){s=a|0\nreturn a===s?s:s+1}}else if(a>=-2147483648)return a|0\nr=Math.ceil(a)\nif(isFinite(r))return r\nthrow A.a(A.H(\"\"+a+\".ceil()\"))},\nj(a){if(a===0&&1/a<0)return\"-0.0\"\nelse return\"\"+a},\ngB(a){var s,r,q,p,o=a|0\nif(a===o)return o&536870911\ns=Math.abs(a)\nr=Math.log(s)/0.6931471805599453|0\nq=Math.pow(2,r)\np=s<1?s/q:q/s\nreturn((p*9007199254740992|0)+(p*3542243181176521|0))*599197+r*1259&536870911},\naA(a,b){var s=a%b\nif(s===0)return 0\nif(s>0)return s\nreturn s+b},\neX(a,b){if((a|0)===a)if(b>=1||b<-1)return a/b|0\nreturn this.fL(a,b)},\nI(a,b){return(a|0)===a?a/b|0:this.fL(a,b)},\nfL(a,b){var s=a/b\nif(s>=-2147483648&&s<=2147483647)return s|0\nif(s>0){if(s!==1/0)return Math.floor(s)}else if(s>-1/0)return Math.ceil(s)\nthrow A.a(A.H(\"Result of truncating division is \"+A.u(s)+\": \"+A.u(a)+\" ~/ \"+b))},\nb0(a,b){if(b<0)throw A.a(A.dS(b))\nreturn b>31?0:a<<b>>>0},\nbl(a,b){var s\nif(b<0)throw A.a(A.dS(b))\nif(a>0)s=this.e2(a,b)\nelse{s=b>31?31:b\ns=a>>s>>>0}return s},\nP(a,b){var s\nif(a>0)s=this.e2(a,b)\nelse{s=b>31?31:b\ns=a>>s>>>0}return s},\nja(a,b){if(0>b)throw A.a(A.dS(b))\nreturn this.e2(a,b)},\ne2(a,b){return b>31?0:a>>>b},\ngV(a){return A.bO(t.v)},\n$iI:1,\n$ib5:1}\nJ.ei.prototype={\ngfV(a){var s,r=a<0?-a-1:a,q=r\nfor(s=32;q>=4294967296;){q=this.I(q,4294967296)\ns+=32}return s-Math.clz32(q)},\ngV(a){return A.bO(t.S)},\n$iL:1,\n$ib:1}\nJ.h9.prototype={\ngV(a){return A.bO(t.i)},\n$iL:1}\nJ.bV.prototype={\njG(a,b){if(b<0)throw A.a(A.dV(a,b))\nif(b>=a.length)A.y(A.dV(a,b))\nreturn a.charCodeAt(b)},\ncM(a,b,c){var s=b.length\nif(c>s)throw A.a(A.a4(c,0,s,null,null))\nreturn new A.iA(b,a,c)},\ned(a,b){return this.cM(a,b,0)},\nha(a,b,c){var s,r,q=null\nif(c<0||c>b.length)throw A.a(A.a4(c,0,b.length,q,q))\ns=a.length\nif(c+s>b.length)return q\nfor(r=0;r<s;++r)if(b.charCodeAt(c+r)!==a.charCodeAt(r))return q\nreturn new A.dg(c,a)},\ndh(a,b){return a+b},\nek(a,b){var s=b.length,r=a.length\nif(s>r)return!1\nreturn b===this.K(a,r-s)},\nhl(a,b,c){A.qa(0,0,a.length,\"startIndex\")\nreturn A.xz(a,b,c,0)},\naQ(a,b){if(typeof b==\"string\")return A.d(a.split(b),t.s)\nelse if(b instanceof A.cs&&b.gfp().exec(\"\").length-2===0)return A.d(a.split(b.b),t.s)\nelse return this.i6(a,b)},\naO(a,b,c,d){var s=A.b9(b,c,a.length)\nreturn A.po(a,b,s,d)},\ni6(a,b){var s,r,q,p,o,n,m=A.d([],t.s)\nfor(s=J.oo(b,a),s=s.gt(s),r=0,q=1;s.k();){p=s.gm()\no=p.gcq()\nn=p.gby()\nq=n-o\nif(q===0&&r===o)continue\nm.push(this.n(a,r,o))\nr=n}if(r<a.length||q>0)m.push(this.K(a,r))\nreturn m},\nE(a,b,c){var s\nif(c<0||c>a.length)throw A.a(A.a4(c,0,a.length,null,null))\nif(typeof b==\"string\"){s=c+b.length\nif(s>a.length)return!1\nreturn b===a.substring(c,s)}return J.tF(b,a,c)!=null},\nu(a,b){return this.E(a,b,0)},\nn(a,b,c){return a.substring(b,A.b9(b,c,a.length))},\nK(a,b){return this.n(a,b,null)},\neM(a){var s,r,q,p=a.trim(),o=p.length\nif(o===0)return p\nif(p.charCodeAt(0)===133){s=J.ue(p,1)\nif(s===o)return\"\"}else s=0\nr=o-1\nq=p.charCodeAt(r)===133?J.uf(p,r):o\nif(s===0&&q===o)return p\nreturn p.substring(s,q)},\nbI(a,b){var s,r\nif(0>=b)return\"\"\nif(b===1||a.length===0)return a\nif(b!==b>>>0)throw A.a(B.aB)\nfor(s=a,r=\"\";!0;){if((b&1)===1)r=s+r\nb=b>>>1\nif(b===0)break\ns+=s}return r},\nkl(a,b,c){var s=b-a.length\nif(s<=0)return a\nreturn this.bI(c,s)+a},\nhd(a,b){var s=b-a.length\nif(s<=0)return a\nreturn a+this.bI(\" \",s)},\naW(a,b,c){var s\nif(c<0||c>a.length)throw A.a(A.a4(c,0,a.length,null,null))\ns=a.indexOf(b,c)\nreturn s},\nk7(a,b){return this.aW(a,b,0)},\nh9(a,b,c){var s,r\nif(c==null)c=a.length\nelse if(c<0||c>a.length)throw A.a(A.a4(c,0,a.length,null,null))\ns=b.length\nr=a.length\nif(c+s>r)c=r-s\nreturn a.lastIndexOf(b,c)},\nd0(a,b){return this.h9(a,b,null)},\nM(a,b){return A.xv(a,b,0)},\nag(a,b){var s\nif(a===b)s=0\nelse s=a<b?-1:1\nreturn s},\nj(a){return a},\ngB(a){var s,r,q\nfor(s=a.length,r=0,q=0;q<s;++q){r=r+a.charCodeAt(q)&536870911\nr=r+((r&524287)<<10)&536870911\nr^=r>>6}r=r+((r&67108863)<<3)&536870911\nr^=r>>11\nreturn r+((r&16383)<<15)&536870911},\ngV(a){return A.bO(t.N)},\ngl(a){return a.length},\ni(a,b){if(!(b>=0&&b<a.length))throw A.a(A.dV(a,b))\nreturn a[b]},\n$iar:1,\n$iL:1,\n$ij:1}\nA.ca.prototype={\ngt(a){return new A.fJ(J.M(this.gan()),A.t(this).h(\"fJ<1,2>\"))},\ngl(a){return J.ae(this.gan())},\ngF(a){return J.iR(this.gan())},\nX(a,b){var s=A.t(this)\nreturn A.e4(J.dZ(this.gan(),b),s.c,s.y[1])},\nah(a,b){var s=A.t(this)\nreturn A.e4(J.iT(this.gan(),b),s.c,s.y[1])},\nN(a,b){return A.t(this).y[1].a(J.fx(this.gan(),b))},\ngG(a){return A.t(this).y[1].a(J.fy(this.gan()))},\ngC(a){return A.t(this).y[1].a(J.iS(this.gan()))},\nj(a){return J.aU(this.gan())}}\nA.fJ.prototype={\nk(){return this.a.k()},\ngm(){return this.$ti.y[1].a(this.a.gm())}}\nA.ck.prototype={\ngan(){return this.a}}\nA.eS.prototype={$iv:1}\nA.eN.prototype={\ni(a,b){return this.$ti.y[1].a(J.aO(this.a,b))},\nq(a,b,c){J.px(this.a,b,this.$ti.c.a(c))},\nco(a,b,c){var s=this.$ti\nreturn A.e4(J.tE(this.a,b,c),s.c,s.y[1])},\nZ(a,b,c,d,e){var s=this.$ti\nJ.tG(this.a,b,c,A.e4(d,s.y[1],s.c),e)},\naj(a,b,c,d){return this.Z(0,b,c,d,0)},\n$iv:1,\n$iq:1}\nA.ah.prototype={\nb8(a,b){return new A.ah(this.a,this.$ti.h(\"@<1>\").H(b).h(\"ah<1,2>\"))},\ngan(){return this.a}}\nA.bX.prototype={\nj(a){return\"LateInitializationError: \"+this.a}}\nA.e6.prototype={\ngl(a){return this.a.length},\ni(a,b){return this.a.charCodeAt(b)}}\nA.oc.prototype={\n$0(){return A.aX(null,t.P)},\n$S:14}\nA.kB.prototype={}\nA.v.prototype={}\nA.P.prototype={\ngt(a){var s=this\nreturn new A.aZ(s,s.gl(s),A.t(s).h(\"aZ<P.E>\"))},\ngF(a){return this.gl(this)===0},\ngG(a){if(this.gl(this)===0)throw A.a(A.ak())\nreturn this.N(0,0)},\ngC(a){var s=this\nif(s.gl(s)===0)throw A.a(A.ak())\nreturn s.N(0,s.gl(s)-1)},\naq(a,b){var s,r,q,p=this,o=p.gl(p)\nif(b.length!==0){if(o===0)return\"\"\ns=A.u(p.N(0,0))\nif(o!==p.gl(p))throw A.a(A.ax(p))\nfor(r=s,q=1;q<o;++q){r=r+b+A.u(p.N(0,q))\nif(o!==p.gl(p))throw A.a(A.ax(p))}return r.charCodeAt(0)==0?r:r}else{for(q=0,r=\"\";q<o;++q){r+=A.u(p.N(0,q))\nif(o!==p.gl(p))throw A.a(A.ax(p))}return r.charCodeAt(0)==0?r:r}},\nc5(a){return this.aq(0,\"\")},\nbd(a,b,c){return new A.D(this,b,A.t(this).h(\"@<P.E>\").H(c).h(\"D<1,2>\"))},\nk5(a,b,c){var s,r,q=this,p=q.gl(q)\nfor(s=b,r=0;r<p;++r){s=c.$2(s,q.N(0,r))\nif(p!==q.gl(q))throw A.a(A.ax(q))}return s},\neo(a,b,c){return this.k5(0,b,c,t.z)},\nX(a,b){return A.b3(this,b,null,A.t(this).h(\"P.E\"))},\nah(a,b){return A.b3(this,0,A.aD(b,\"count\",t.S),A.t(this).h(\"P.E\"))},\naz(a,b){return A.ay(this,!0,A.t(this).h(\"P.E\"))},\ncj(a){return this.az(0,!0)}}\nA.cw.prototype={\nhN(a,b,c,d){var s,r=this.b\nA.ab(r,\"start\")\ns=this.c\nif(s!=null){A.ab(s,\"end\")\nif(r>s)throw A.a(A.a4(r,0,s,\"start\",null))}},\ngie(){var s=J.ae(this.a),r=this.c\nif(r==null||r>s)return s\nreturn r},\ngjf(){var s=J.ae(this.a),r=this.b\nif(r>s)return s\nreturn r},\ngl(a){var s,r=J.ae(this.a),q=this.b\nif(q>=r)return 0\ns=this.c\nif(s==null||s>=r)return r-q\nreturn s-q},\nN(a,b){var s=this,r=s.gjf()+b\nif(b<0||r>=s.gie())throw A.a(A.h4(b,s.gl(0),s,null,\"index\"))\nreturn J.fx(s.a,r)},\nX(a,b){var s,r,q=this\nA.ab(b,\"count\")\ns=q.b+b\nr=q.c\nif(r!=null&&s>=r)return new A.cq(q.$ti.h(\"cq<1>\"))\nreturn A.b3(q.a,s,r,q.$ti.c)},\nah(a,b){var s,r,q,p=this\nA.ab(b,\"count\")\ns=p.c\nr=p.b\nq=r+b\nif(s==null)return A.b3(p.a,r,q,p.$ti.c)\nelse{if(s<q)return p\nreturn A.b3(p.a,r,q,p.$ti.c)}},\naz(a,b){var s,r,q,p=this,o=p.b,n=p.a,m=J.V(n),l=m.gl(n),k=p.c\nif(k!=null&&k<l)l=k\ns=l-o\nif(s<=0){n=J.pV(0,p.$ti.c)\nreturn n}r=A.b_(s,m.N(n,o),!1,p.$ti.c)\nfor(q=1;q<s;++q){r[q]=m.N(n,o+q)\nif(m.gl(n)<l)throw A.a(A.ax(p))}return r}}\nA.aZ.prototype={\ngm(){var s=this.d\nreturn s==null?this.$ti.c.a(s):s},\nk(){var s,r=this,q=r.a,p=J.V(q),o=p.gl(q)\nif(r.b!==o)throw A.a(A.ax(q))\ns=r.c\nif(s>=o){r.d=null\nreturn!1}r.d=p.N(q,s);++r.c\nreturn!0}}\nA.az.prototype={\ngt(a){return new A.b0(J.M(this.a),this.b,A.t(this).h(\"b0<1,2>\"))},\ngl(a){return J.ae(this.a)},\ngF(a){return J.iR(this.a)},\ngG(a){return this.b.$1(J.fy(this.a))},\ngC(a){return this.b.$1(J.iS(this.a))},\nN(a,b){return this.b.$1(J.fx(this.a,b))}}\nA.cp.prototype={$iv:1}\nA.b0.prototype={\nk(){var s=this,r=s.b\nif(r.k()){s.a=s.c.$1(r.gm())\nreturn!0}s.a=null\nreturn!1},\ngm(){var s=this.a\nreturn s==null?this.$ti.y[1].a(s):s}}\nA.D.prototype={\ngl(a){return J.ae(this.a)},\nN(a,b){return this.b.$1(J.fx(this.a,b))}}\nA.aT.prototype={\ngt(a){return new A.eH(J.M(this.a),this.b)},\nbd(a,b,c){return new A.az(this,b,this.$ti.h(\"@<1>\").H(c).h(\"az<1,2>\"))}}\nA.eH.prototype={\nk(){var s,r\nfor(s=this.a,r=this.b;s.k();)if(r.$1(s.gm()))return!0\nreturn!1},\ngm(){return this.a.gm()}}\nA.ed.prototype={\ngt(a){return new A.fY(J.M(this.a),this.b,B.a0,this.$ti.h(\"fY<1,2>\"))}}\nA.fY.prototype={\ngm(){var s=this.d\nreturn s==null?this.$ti.y[1].a(s):s},\nk(){var s,r,q=this,p=q.c\nif(p==null)return!1\nfor(s=q.a,r=q.b;!p.k();){q.d=null\nif(s.k()){q.c=null\np=J.M(r.$1(s.gm()))\nq.c=p}else return!1}q.d=q.c.gm()\nreturn!0}}\nA.cx.prototype={\ngt(a){return new A.hF(J.M(this.a),this.b,A.t(this).h(\"hF<1>\"))}}\nA.eb.prototype={\ngl(a){var s=J.ae(this.a),r=this.b\nif(s>r)return r\nreturn s},\n$iv:1}\nA.hF.prototype={\nk(){if(--this.b>=0)return this.a.k()\nthis.b=-1\nreturn!1},\ngm(){if(this.b<0){this.$ti.c.a(null)\nreturn null}return this.a.gm()}}\nA.bB.prototype={\nX(a,b){A.bR(b,\"count\")\nA.ab(b,\"count\")\nreturn new A.bB(this.a,this.b+b,A.t(this).h(\"bB<1>\"))},\ngt(a){return new A.hy(J.M(this.a),this.b)}}\nA.cV.prototype={\ngl(a){var s=J.ae(this.a)-this.b\nif(s>=0)return s\nreturn 0},\nX(a,b){A.bR(b,\"count\")\nA.ab(b,\"count\")\nreturn new A.cV(this.a,this.b+b,this.$ti)},\n$iv:1}\nA.hy.prototype={\nk(){var s,r\nfor(s=this.a,r=0;r<this.b;++r)s.k()\nthis.b=0\nreturn s.k()},\ngm(){return this.a.gm()}}\nA.ex.prototype={\ngt(a){return new A.hz(J.M(this.a),this.b)}}\nA.hz.prototype={\nk(){var s,r,q=this\nif(!q.c){q.c=!0\nfor(s=q.a,r=q.b;s.k();)if(!r.$1(s.gm()))return!0}return q.a.k()},\ngm(){return this.a.gm()}}\nA.cq.prototype={\ngt(a){return B.a0},\ngF(a){return!0},\ngl(a){return 0},\ngG(a){throw A.a(A.ak())},\ngC(a){throw A.a(A.ak())},\nN(a,b){throw A.a(A.a4(b,0,0,\"index\",null))},\nbd(a,b,c){return new A.cq(c.h(\"cq<0>\"))},\nX(a,b){A.ab(b,\"count\")\nreturn this},\nah(a,b){A.ab(b,\"count\")\nreturn this}}\nA.fV.prototype={\nk(){return!1},\ngm(){throw A.a(A.ak())}}\nA.eI.prototype={\ngt(a){return new A.hY(J.M(this.a),this.$ti.h(\"hY<1>\"))}}\nA.hY.prototype={\nk(){var s,r\nfor(s=this.a,r=this.$ti.c;s.k();)if(r.b(s.gm()))return!0\nreturn!1},\ngm(){return this.$ti.c.a(this.a.gm())}}\nA.bt.prototype={\ngl(a){return J.ae(this.a)},\ngF(a){return J.iR(this.a)},\ngG(a){return new A.ap(this.b,J.fy(this.a))},\nN(a,b){return new A.ap(b+this.b,J.fx(this.a,b))},\nah(a,b){A.bR(b,\"count\")\nA.ab(b,\"count\")\nreturn new A.bt(J.iT(this.a,b),this.b,A.t(this).h(\"bt<1>\"))},\nX(a,b){A.bR(b,\"count\")\nA.ab(b,\"count\")\nreturn new A.bt(J.dZ(this.a,b),b+this.b,A.t(this).h(\"bt<1>\"))},\ngt(a){return new A.eg(J.M(this.a),this.b)}}\nA.co.prototype={\ngC(a){var s,r=this.a,q=J.V(r),p=q.gl(r)\nif(p<=0)throw A.a(A.ak())\ns=q.gC(r)\nif(p!==q.gl(r))throw A.a(A.ax(this))\nreturn new A.ap(p-1+this.b,s)},\nah(a,b){A.bR(b,\"count\")\nA.ab(b,\"count\")\nreturn new A.co(J.iT(this.a,b),this.b,this.$ti)},\nX(a,b){A.bR(b,\"count\")\nA.ab(b,\"count\")\nreturn new A.co(J.dZ(this.a,b),this.b+b,this.$ti)},\n$iv:1}\nA.eg.prototype={\nk(){if(++this.c>=0&&this.a.k())return!0\nthis.c=-2\nreturn!1},\ngm(){var s=this.c\nreturn s>=0?new A.ap(this.b+s,this.a.gm()):A.y(A.ak())}}\nA.ee.prototype={}\nA.hJ.prototype={\nq(a,b,c){throw A.a(A.H(\"Cannot modify an unmodifiable list\"))},\nZ(a,b,c,d,e){throw A.a(A.H(\"Cannot modify an unmodifiable list\"))},\naj(a,b,c,d){return this.Z(0,b,c,d,0)}}\nA.dh.prototype={}\nA.ew.prototype={\ngl(a){return J.ae(this.a)},\nN(a,b){var s=this.a,r=J.V(s)\nreturn r.N(s,r.gl(s)-1-b)}}\nA.hE.prototype={\ngB(a){var s=this._hashCode\nif(s!=null)return s\ns=664597*B.a.gB(this.a)&536870911\nthis._hashCode=s\nreturn s},\nj(a){return'Symbol(\"'+this.a+'\")'},\nO(a,b){if(b==null)return!1\nreturn b instanceof A.hE&&this.a===b.a}}\nA.fn.prototype={}\nA.ap.prototype={$r:\"+(1,2)\",$s:1}\nA.cH.prototype={$r:\"+file,outFlags(1,2)\",$s:2}\nA.e7.prototype={\nj(a){return A.oD(this)},\ngel(){return new A.dJ(this.jP(),A.t(this).h(\"dJ<bv<1,2>>\"))},\njP(){var s=this\nreturn function(){var r=0,q=1,p,o,n,m\nreturn function $async$gel(a,b,c){if(b===1){p=c\nr=q}while(true)switch(r){case 0:o=s.ga_(),o=o.gt(o),n=A.t(s).h(\"bv<1,2>\")\ncase 2:if(!o.k()){r=3\nbreak}m=o.gm()\nr=4\nreturn a.b=new A.bv(m,s.i(0,m),n),1\ncase 4:r=2\nbreak\ncase 3:return 0\ncase 1:return a.c=p,3}}}},\n$iaa:1}\nA.e8.prototype={\ngl(a){return this.b.length},\ngfl(){var s=this.$keys\nif(s==null){s=Object.keys(this.a)\nthis.$keys=s}return s},\na4(a){if(typeof a!=\"string\")return!1\nif(\"__proto__\"===a)return!1\nreturn this.a.hasOwnProperty(a)},\ni(a,b){if(!this.a4(b))return null\nreturn this.b[this.a[b]]},\naa(a,b){var s,r,q=this.gfl(),p=this.b\nfor(s=q.length,r=0;r<s;++r)b.$2(q[r],p[r])},\nga_(){return new A.cG(this.gfl(),this.$ti.h(\"cG<1>\"))},\ngaP(){return new A.cG(this.b,this.$ti.h(\"cG<2>\"))}}\nA.cG.prototype={\ngl(a){return this.a.length},\ngF(a){return 0===this.a.length},\ngt(a){var s=this.a\nreturn new A.il(s,s.length,this.$ti.h(\"il<1>\"))}}\nA.il.prototype={\ngm(){var s=this.d\nreturn s==null?this.$ti.c.a(s):s},\nk(){var s=this,r=s.c\nif(r>=s.b){s.d=null\nreturn!1}s.d=s.a[r]\ns.c=r+1\nreturn!0}}\nA.k3.prototype={\nO(a,b){if(b==null)return!1\nreturn b instanceof A.eh&&this.a.O(0,b.a)&&A.pi(this)===A.pi(b)},\ngB(a){return A.es(this.a,A.pi(this),B.f,B.f)},\nj(a){var s=B.c.aq([A.bO(this.$ti.c)],\", \")\nreturn this.a.j(0)+\" with \"+(\"<\"+s+\">\")}}\nA.eh.prototype={\n$2(a,b){return this.a.$1$2(a,b,this.$ti.y[0])},\n$4(a,b,c,d){return this.a.$1$4(a,b,c,d,this.$ti.y[0])},\n$S(){return A.xb(A.o0(this.a),this.$ti)}}\nA.lc.prototype={\nar(a){var s,r,q=this,p=new RegExp(q.a).exec(a)\nif(p==null)return null\ns=Object.create(null)\nr=q.b\nif(r!==-1)s.arguments=p[r+1]\nr=q.c\nif(r!==-1)s.argumentsExpr=p[r+1]\nr=q.d\nif(r!==-1)s.expr=p[r+1]\nr=q.e\nif(r!==-1)s.method=p[r+1]\nr=q.f\nif(r!==-1)s.receiver=p[r+1]\nreturn s}}\nA.er.prototype={\nj(a){return\"Null check operator used on a null value\"}}\nA.hb.prototype={\nj(a){var s,r=this,q=\"NoSuchMethodError: method not found: '\",p=r.b\nif(p==null)return\"NoSuchMethodError: \"+r.a\ns=r.c\nif(s==null)return q+p+\"' (\"+r.a+\")\"\nreturn q+p+\"' on '\"+s+\"' (\"+r.a+\")\"}}\nA.hI.prototype={\nj(a){var s=this.a\nreturn s.length===0?\"Error\":\"Error: \"+s}}\nA.hp.prototype={\nj(a){return\"Throw of null ('\"+(this.a===null?\"null\":\"undefined\")+\"' from JavaScript)\"},\n$ia5:1}\nA.ec.prototype={}\nA.fa.prototype={\nj(a){var s,r=this.b\nif(r!=null)return r\nr=this.a\ns=r!==null&&typeof r===\"object\"?r.stack:null\nreturn this.b=s==null?\"\":s},\n$ia0:1}\nA.cl.prototype={\nj(a){var s=this.constructor,r=s==null?null:s.name\nreturn\"Closure '\"+A.rO(r==null?\"unknown\":r)+\"'\"},\ngkI(){return this},\n$C:\"$1\",\n$R:1,\n$D:null}\nA.j9.prototype={$C:\"$0\",$R:0}\nA.ja.prototype={$C:\"$2\",$R:2}\nA.l2.prototype={}\nA.kT.prototype={\nj(a){var s=this.$static_name\nif(s==null)return\"Closure of unknown static method\"\nreturn\"Closure '\"+A.rO(s)+\"'\"}}\nA.e2.prototype={\nO(a,b){if(b==null)return!1\nif(this===b)return!0\nif(!(b instanceof A.e2))return!1\nreturn this.$_target===b.$_target&&this.a===b.a},\ngB(a){return(A.pm(this.a)^A.ev(this.$_target))>>>0},\nj(a){return\"Closure '\"+this.$_name+\"' of \"+(\"Instance of '\"+A.kp(this.a)+\"'\")}}\nA.i8.prototype={\nj(a){return\"Reading static variable '\"+this.a+\"' during its initialization\"}}\nA.hv.prototype={\nj(a){return\"RuntimeError: \"+this.a}}\nA.bu.prototype={\ngl(a){return this.a},\ngF(a){return this.a===0},\nga_(){return new A.b8(this,A.t(this).h(\"b8<1>\"))},\ngaP(){var s=A.t(this)\nreturn A.en(new A.b8(this,s.h(\"b8<1>\")),new A.kb(this),s.c,s.y[1])},\na4(a){var s,r\nif(typeof a==\"string\"){s=this.b\nif(s==null)return!1\nreturn s[a]!=null}else if(typeof a==\"number\"&&(a&0x3fffffff)===a){r=this.c\nif(r==null)return!1\nreturn r[a]!=null}else return this.k8(a)},\nk8(a){var s=this.d\nif(s==null)return!1\nreturn this.d_(s[this.cZ(a)],a)>=0},\naJ(a,b){b.aa(0,new A.ka(this))},\ni(a,b){var s,r,q,p,o=null\nif(typeof b==\"string\"){s=this.b\nif(s==null)return o\nr=s[b]\nq=r==null?o:r.b\nreturn q}else if(typeof b==\"number\"&&(b&0x3fffffff)===b){p=this.c\nif(p==null)return o\nr=p[b]\nq=r==null?o:r.b\nreturn q}else return this.k9(b)},\nk9(a){var s,r,q=this.d\nif(q==null)return null\ns=q[this.cZ(a)]\nr=this.d_(s,a)\nif(r<0)return null\nreturn s[r].b},\nq(a,b,c){var s,r,q=this\nif(typeof b==\"string\"){s=q.b\nq.eY(s==null?q.b=q.dW():s,b,c)}else if(typeof b==\"number\"&&(b&0x3fffffff)===b){r=q.c\nq.eY(r==null?q.c=q.dW():r,b,c)}else q.kb(b,c)},\nkb(a,b){var s,r,q,p=this,o=p.d\nif(o==null)o=p.d=p.dW()\ns=p.cZ(a)\nr=o[s]\nif(r==null)o[s]=[p.dq(a,b)]\nelse{q=p.d_(r,a)\nif(q>=0)r[q].b=b\nelse r.push(p.dq(a,b))}},\nhg(a,b){var s,r,q=this\nif(q.a4(a)){s=q.i(0,a)\nreturn s==null?A.t(q).y[1].a(s):s}r=b.$0()\nq.q(0,a,r)\nreturn r},\nA(a,b){var s=this\nif(typeof b==\"string\")return s.eZ(s.b,b)\nelse if(typeof b==\"number\"&&(b&0x3fffffff)===b)return s.eZ(s.c,b)\nelse return s.ka(b)},\nka(a){var s,r,q,p,o=this,n=o.d\nif(n==null)return null\ns=o.cZ(a)\nr=n[s]\nq=o.d_(r,a)\nif(q<0)return null\np=r.splice(q,1)[0]\no.f_(p)\nif(r.length===0)delete n[s]\nreturn p.b},\nc1(a){var s=this\nif(s.a>0){s.b=s.c=s.d=s.e=s.f=null\ns.a=0\ns.dn()}},\naa(a,b){var s=this,r=s.e,q=s.r\nfor(;r!=null;){b.$2(r.a,r.b)\nif(q!==s.r)throw A.a(A.ax(s))\nr=r.c}},\neY(a,b,c){var s=a[b]\nif(s==null)a[b]=this.dq(b,c)\nelse s.b=c},\neZ(a,b){var s\nif(a==null)return null\ns=a[b]\nif(s==null)return null\nthis.f_(s)\ndelete a[b]\nreturn s.b},\ndn(){this.r=this.r+1&1073741823},\ndq(a,b){var s,r=this,q=new A.ke(a,b)\nif(r.e==null)r.e=r.f=q\nelse{s=r.f\ns.toString\nq.d=s\nr.f=s.c=q}++r.a\nr.dn()\nreturn q},\nf_(a){var s=this,r=a.d,q=a.c\nif(r==null)s.e=q\nelse r.c=q\nif(q==null)s.f=r\nelse q.d=r;--s.a\ns.dn()},\ncZ(a){return J.aw(a)&1073741823},\nd_(a,b){var s,r\nif(a==null)return-1\ns=a.length\nfor(r=0;r<s;++r)if(J.X(a[r].a,b))return r\nreturn-1},\nj(a){return A.oD(this)},\ndW(){var s=Object.create(null)\ns[\"<non-identifier-key>\"]=s\ndelete s[\"<non-identifier-key>\"]\nreturn s}}\nA.kb.prototype={\n$1(a){var s=this.a,r=s.i(0,a)\nreturn r==null?A.t(s).y[1].a(r):r},\n$S(){return A.t(this.a).h(\"2(1)\")}}\nA.ka.prototype={\n$2(a,b){this.a.q(0,a,b)},\n$S(){return A.t(this.a).h(\"~(1,2)\")}}\nA.ke.prototype={}\nA.b8.prototype={\ngl(a){return this.a.a},\ngF(a){return this.a.a===0},\ngt(a){var s=this.a,r=new A.he(s,s.r)\nr.c=s.e\nreturn r}}\nA.he.prototype={\ngm(){return this.d},\nk(){var s,r=this,q=r.a\nif(r.b!==q.r)throw A.a(A.ax(q))\ns=r.c\nif(s==null){r.d=null\nreturn!1}else{r.d=s.a\nr.c=s.c\nreturn!0}}}\nA.o6.prototype={\n$1(a){return this.a(a)},\n$S:44}\nA.o7.prototype={\n$2(a,b){return this.a(a,b)},\n$S:62}\nA.o8.prototype={\n$1(a){return this.a(a)},\n$S:109}\nA.f6.prototype={\nj(a){return this.fP(!1)},\nfP(a){var s,r,q,p,o,n=this.ih(),m=this.fi(),l=(a?\"\"+\"Record \":\"\")+\"(\"\nfor(s=n.length,r=\"\",q=0;q<s;++q,r=\", \"){l+=r\np=n[q]\nif(typeof p==\"string\")l=l+p+\": \"\no=m[q]\nl=a?l+A.q5(o):l+A.u(o)}l+=\")\"\nreturn l.charCodeAt(0)==0?l:l},\nih(){var s,r=this.$s\nfor(;$.ng.length<=r;)$.ng.push(null)\ns=$.ng[r]\nif(s==null){s=this.i1()\n$.ng[r]=s}return s},\ni1(){var s,r,q,p=this.$r,o=p.indexOf(\"(\"),n=p.substring(1,o),m=p.substring(o),l=m===\"()\"?0:m.replace(/[^,]/g,\"\").length+1,k=t.K,j=J.pU(l,k)\nfor(s=0;s<l;++s)j[s]=s\nif(n!==\"\"){r=n.split(\",\")\ns=r.length\nfor(q=l;s>0;){--q;--s\nj[q]=r[s]}}return A.aG(j,k)}}\nA.is.prototype={\nfi(){return[this.a,this.b]},\nO(a,b){if(b==null)return!1\nreturn b instanceof A.is&&this.$s===b.$s&&J.X(this.a,b.a)&&J.X(this.b,b.b)},\ngB(a){return A.es(this.$s,this.a,this.b,B.f)}}\nA.cs.prototype={\nj(a){return\"RegExp/\"+this.a+\"/\"+this.b.flags},\ngfq(){var s=this,r=s.c\nif(r!=null)return r\nr=s.b\nreturn s.c=A.oz(s.a,r.multiline,!r.ignoreCase,r.unicode,r.dotAll,!0)},\ngfp(){var s=this,r=s.d\nif(r!=null)return r\nr=s.b\nreturn s.d=A.oz(s.a+\"|()\",r.multiline,!r.ignoreCase,r.unicode,r.dotAll,!0)},\na9(a){var s=this.b.exec(a)\nif(s==null)return null\nreturn new A.dz(s)},\ncM(a,b,c){var s=b.length\nif(c>s)throw A.a(A.a4(c,0,s,null,null))\nreturn new A.hZ(this,b,c)},\ned(a,b){return this.cM(0,b,0)},\nfe(a,b){var s,r=this.gfq()\nr.lastIndex=b\ns=r.exec(a)\nif(s==null)return null\nreturn new A.dz(s)},\nig(a,b){var s,r=this.gfp()\nr.lastIndex=b\ns=r.exec(a)\nif(s==null)return null\nif(s.pop()!=null)return null\nreturn new A.dz(s)},\nha(a,b,c){if(c<0||c>b.length)throw A.a(A.a4(c,0,b.length,null,null))\nreturn this.ig(b,c)}}\nA.dz.prototype={\ngcq(){return this.b.index},\ngby(){var s=this.b\nreturn s.index+s[0].length},\ni(a,b){return this.b[b]},\naN(a){var s,r=this.b.groups\nif(r!=null){s=r[a]\nif(s!=null||a in r)return s}throw A.a(A.ag(a,\"name\",\"Not a capture group name\"))},\n$ieo:1,\n$ihs:1}\nA.hZ.prototype={\ngt(a){return new A.lO(this.a,this.b,this.c)}}\nA.lO.prototype={\ngm(){var s=this.d\nreturn s==null?t.cz.a(s):s},\nk(){var s,r,q,p,o,n,m=this,l=m.b\nif(l==null)return!1\ns=m.c\nr=l.length\nif(s<=r){q=m.a\np=q.fe(l,s)\nif(p!=null){m.d=p\no=p.gby()\nif(p.b.index===o){s=!1\nif(q.b.unicode){q=m.c\nn=q+1\nif(n<r){r=l.charCodeAt(q)\nif(r>=55296&&r<=56319){s=l.charCodeAt(n)\ns=s>=56320&&s<=57343}}}o=(s?o+1:o)+1}m.c=o\nreturn!0}}m.b=m.d=null\nreturn!1}}\nA.dg.prototype={\ngby(){return this.a+this.c.length},\ni(a,b){if(b!==0)A.y(A.kt(b,null))\nreturn this.c},\n$ieo:1,\ngcq(){return this.a}}\nA.iA.prototype={\ngt(a){return new A.ns(this.a,this.b,this.c)},\ngG(a){var s=this.b,r=this.a.indexOf(s,this.c)\nif(r>=0)return new A.dg(r,s)\nthrow A.a(A.ak())}}\nA.ns.prototype={\nk(){var s,r,q=this,p=q.c,o=q.b,n=o.length,m=q.a,l=m.length\nif(p+n>l){q.d=null\nreturn!1}s=m.indexOf(o,p)\nif(s<0){q.c=l+1\nq.d=null\nreturn!1}r=s+n\nq.d=new A.dg(s,o)\nq.c=r===q.c?r+1:r\nreturn!0},\ngm(){var s=this.d\ns.toString\nreturn s}}\nA.m3.prototype={\naf(){var s=this.b\nif(s===this)throw A.a(A.ug(this.a))\nreturn s}}\nA.d_.prototype={\ngV(a){return B.b7},\n$iL:1,\n$id_:1,\n$iop:1}\nA.ep.prototype={\niu(a,b,c,d){var s=A.a4(b,0,c,d,null)\nthrow A.a(s)},\nf7(a,b,c,d){if(b>>>0!==b||b>c)this.iu(a,b,c,d)}}\nA.d0.prototype={\ngV(a){return B.b8},\n$iL:1,\n$id0:1,\n$ioq:1}\nA.d2.prototype={\ngl(a){return a.length},\nfI(a,b,c,d,e){var s,r,q=a.length\nthis.f7(a,b,q,\"start\")\nthis.f7(a,c,q,\"end\")\nif(b>c)throw A.a(A.a4(b,0,c,null,null))\ns=c-b\nif(e<0)throw A.a(A.K(e,null))\nr=d.length\nif(r-e<s)throw A.a(A.B(\"Not enough elements\"))\nif(e!==0||r!==s)d=d.subarray(e,e+s)\na.set(d,b)},\n$iar:1,\n$iaP:1}\nA.c_.prototype={\ni(a,b){A.bK(b,a,a.length)\nreturn a[b]},\nq(a,b,c){A.bK(b,a,a.length)\na[b]=c},\nZ(a,b,c,d,e){if(t.aV.b(d)){this.fI(a,b,c,d,e)\nreturn}this.eV(a,b,c,d,e)},\naj(a,b,c,d){return this.Z(a,b,c,d,0)},\n$iv:1,\n$if:1,\n$iq:1}\nA.aR.prototype={\nq(a,b,c){A.bK(b,a,a.length)\na[b]=c},\nZ(a,b,c,d,e){if(t.eB.b(d)){this.fI(a,b,c,d,e)\nreturn}this.eV(a,b,c,d,e)},\naj(a,b,c,d){return this.Z(a,b,c,d,0)},\n$iv:1,\n$if:1,\n$iq:1}\nA.hg.prototype={\ngV(a){return B.b9},\na0(a,b,c){return new Float32Array(a.subarray(b,A.ce(b,c,a.length)))},\n$iL:1,\n$ijN:1}\nA.hh.prototype={\ngV(a){return B.ba},\na0(a,b,c){return new Float64Array(a.subarray(b,A.ce(b,c,a.length)))},\n$iL:1,\n$ijO:1}\nA.hi.prototype={\ngV(a){return B.bb},\ni(a,b){A.bK(b,a,a.length)\nreturn a[b]},\na0(a,b,c){return new Int16Array(a.subarray(b,A.ce(b,c,a.length)))},\n$iL:1,\n$ik4:1}\nA.d1.prototype={\ngV(a){return B.bc},\ni(a,b){A.bK(b,a,a.length)\nreturn a[b]},\na0(a,b,c){return new Int32Array(a.subarray(b,A.ce(b,c,a.length)))},\n$iL:1,\n$id1:1,\n$ik5:1}\nA.hj.prototype={\ngV(a){return B.bd},\ni(a,b){A.bK(b,a,a.length)\nreturn a[b]},\na0(a,b,c){return new Int8Array(a.subarray(b,A.ce(b,c,a.length)))},\n$iL:1,\n$ik6:1}\nA.hk.prototype={\ngV(a){return B.bf},\ni(a,b){A.bK(b,a,a.length)\nreturn a[b]},\na0(a,b,c){return new Uint16Array(a.subarray(b,A.ce(b,c,a.length)))},\n$iL:1,\n$ile:1}\nA.hl.prototype={\ngV(a){return B.bg},\ni(a,b){A.bK(b,a,a.length)\nreturn a[b]},\na0(a,b,c){return new Uint32Array(a.subarray(b,A.ce(b,c,a.length)))},\n$iL:1,\n$ilf:1}\nA.eq.prototype={\ngV(a){return B.bh},\ngl(a){return a.length},\ni(a,b){A.bK(b,a,a.length)\nreturn a[b]},\na0(a,b,c){return new Uint8ClampedArray(a.subarray(b,A.ce(b,c,a.length)))},\n$iL:1,\n$ilg:1}\nA.bx.prototype={\ngV(a){return B.bi},\ngl(a){return a.length},\ni(a,b){A.bK(b,a,a.length)\nreturn a[b]},\na0(a,b,c){return new Uint8Array(a.subarray(b,A.ce(b,c,a.length)))},\n$iL:1,\n$ibx:1,\n$iat:1}\nA.f1.prototype={}\nA.f2.prototype={}\nA.f3.prototype={}\nA.f4.prototype={}\nA.b1.prototype={\nh(a){return A.fi(v.typeUniverse,this,a)},\nH(a){return A.qT(v.typeUniverse,this,a)}}\nA.ig.prototype={}\nA.ny.prototype={\nj(a){return A.aK(this.a,null)}}\nA.ib.prototype={\nj(a){return this.a}}\nA.fe.prototype={$ibD:1}\nA.lQ.prototype={\n$1(a){var s=this.a,r=s.a\ns.a=null\nr.$0()},\n$S:25}\nA.lP.prototype={\n$1(a){var s,r\nthis.a.a=a\ns=this.b\nr=this.c\ns.firstChild?s.removeChild(r):s.appendChild(r)},\n$S:55}\nA.lR.prototype={\n$0(){this.a.$0()},\n$S:9}\nA.lS.prototype={\n$0(){this.a.$0()},\n$S:9}\nA.iD.prototype={\nhR(a,b){if(self.setTimeout!=null)self.setTimeout(A.cf(new A.nx(this,b),0),a)\nelse throw A.a(A.H(\"`setTimeout()` not found.\"))},\nhS(a,b){if(self.setTimeout!=null)self.setInterval(A.cf(new A.nw(this,a,Date.now(),b),0),a)\nelse throw A.a(A.H(\"Periodic timer.\"))}}\nA.nx.prototype={\n$0(){this.a.c=1\nthis.b.$0()},\n$S:0}\nA.nw.prototype={\n$0(){var s,r=this,q=r.a,p=q.c+1,o=r.b\nif(o>0){s=Date.now()-r.c\nif(s>(p+1)*o)p=B.b.eX(s,o)}q.c=p\nr.d.$1(q)},\n$S:9}\nA.i_.prototype={\nL(a){var s,r=this\nif(a==null)a=r.$ti.c.a(a)\nif(!r.b)r.a.b1(a)\nelse{s=r.a\nif(r.$ti.h(\"C<1>\").b(a))s.f6(a)\nelse s.bq(a)}},\nbx(a,b){var s=this.a\nif(this.b)s.W(a,b)\nelse s.aE(a,b)}}\nA.nI.prototype={\n$1(a){return this.a.$2(0,a)},\n$S:16}\nA.nJ.prototype={\n$2(a,b){this.a.$2(1,new A.ec(a,b))},\n$S:45}\nA.nZ.prototype={\n$2(a,b){this.a(a,b)},\n$S:54}\nA.iB.prototype={\ngm(){return this.b},\niY(a,b){var s,r,q\na=a\nb=b\ns=this.a\nfor(;!0;)try{r=s(this,a,b)\nreturn r}catch(q){b=q\na=1}},\nk(){var s,r,q,p,o=this,n=null,m=0\nfor(;!0;){s=o.d\nif(s!=null)try{if(s.k()){o.b=s.gm()\nreturn!0}else o.d=null}catch(r){n=r\nm=1\no.d=null}q=o.iY(m,n)\nif(1===q)return!0\nif(0===q){o.b=null\np=o.e\nif(p==null||p.length===0){o.a=A.qO\nreturn!1}o.a=p.pop()\nm=0\nn=null\ncontinue}if(2===q){m=0\nn=null\ncontinue}if(3===q){n=o.c\no.c=null\np=o.e\nif(p==null||p.length===0){o.b=null\no.a=A.qO\nthrow n\nreturn!1}o.a=p.pop()\nm=1\ncontinue}throw A.a(A.B(\"sync*\"))}return!1},\nkJ(a){var s,r,q=this\nif(a instanceof A.dJ){s=a.a()\nr=q.e\nif(r==null)r=q.e=[]\nr.push(q.a)\nq.a=s\nreturn 2}else{q.d=J.M(a)\nreturn 2}}}\nA.dJ.prototype={\ngt(a){return new A.iB(this.a())}}\nA.cS.prototype={\nj(a){return A.u(this.a)},\n$iO:1,\ngbJ(){return this.b}}\nA.eM.prototype={}\nA.cB.prototype={\nal(){},\nam(){}}\nA.cA.prototype={\ngbM(){return this.c<4},\nfC(a){var s=a.CW,r=a.ch\nif(s==null)this.d=r\nelse s.ch=r\nif(r==null)this.e=s\nelse r.CW=s\na.CW=a\na.ch=a},\nfK(a,b,c,d){var s,r,q,p,o,n,m,l,k,j=this\nif((j.c&4)!==0){s=$.i\nr=new A.eR(s)\nA.oh(r.gfs())\nif(c!=null)r.c=s.au(c,t.H)\nreturn r}s=A.t(j)\nr=$.i\nq=d?1:0\np=b!=null?32:0\no=A.i5(r,a,s.c)\nn=A.i6(r,b)\nm=c==null?A.rv():c\nl=new A.cB(j,o,n,r.au(m,t.H),r,q|p,s.h(\"cB<1>\"))\nl.CW=l\nl.ch=l\nl.ay=j.c&1\nk=j.e\nj.e=l\nl.ch=null\nl.CW=k\nif(k==null)j.d=l\nelse k.ch=l\nif(j.d===l)A.iM(j.a)\nreturn l},\nfu(a){var s,r=this\nA.t(r).h(\"cB<1>\").a(a)\nif(a.ch===a)return null\ns=a.ay\nif((s&2)!==0)a.ay=s|4\nelse{r.fC(a)\nif((r.c&2)===0&&r.d==null)r.du()}return null},\nfv(a){},\nfw(a){},\nbK(){if((this.c&4)!==0)return new A.b2(\"Cannot add new events after calling close\")\nreturn new A.b2(\"Cannot add new events while doing an addStream\")},\nv(a,b){if(!this.gbM())throw A.a(this.bK())\nthis.b3(b)},\na3(a,b){var s\nA.aD(a,\"error\",t.K)\nif(!this.gbM())throw A.a(this.bK())\ns=$.i.aL(a,b)\nif(s!=null){a=s.a\nb=s.b}this.b5(a,b)},\np(){var s,r,q=this\nif((q.c&4)!==0){s=q.r\ns.toString\nreturn s}if(!q.gbM())throw A.a(q.bK())\nq.c|=4\nr=q.r\nif(r==null)r=q.r=new A.k($.i,t.D)\nq.b4()\nreturn r},\ndK(a){var s,r,q,p=this,o=p.c\nif((o&2)!==0)throw A.a(A.B(u.o))\ns=p.d\nif(s==null)return\nr=o&1\np.c=o^3\nfor(;s!=null;){o=s.ay\nif((o&1)===r){s.ay=o|2\na.$1(s)\no=s.ay^=1\nq=s.ch\nif((o&4)!==0)p.fC(s)\ns.ay&=4294967293\ns=q}else s=s.ch}p.c&=4294967293\nif(p.d==null)p.du()},\ndu(){if((this.c&4)!==0){var s=this.r\nif((s.a&30)===0)s.b1(null)}A.iM(this.b)},\n$ia9:1}\nA.fd.prototype={\ngbM(){return A.cA.prototype.gbM.call(this)&&(this.c&2)===0},\nbK(){if((this.c&2)!==0)return new A.b2(u.o)\nreturn this.hI()},\nb3(a){var s=this,r=s.d\nif(r==null)return\nif(r===s.e){s.c|=2\nr.bp(a)\ns.c&=4294967293\nif(s.d==null)s.du()\nreturn}s.dK(new A.nt(s,a))},\nb5(a,b){if(this.d==null)return\nthis.dK(new A.nv(this,a,b))},\nb4(){var s=this\nif(s.d!=null)s.dK(new A.nu(s))\nelse s.r.b1(null)}}\nA.nt.prototype={\n$1(a){a.bp(this.b)},\n$S(){return this.a.$ti.h(\"~(af<1>)\")}}\nA.nv.prototype={\n$1(a){a.bn(this.b,this.c)},\n$S(){return this.a.$ti.h(\"~(af<1>)\")}}\nA.nu.prototype={\n$1(a){a.cv()},\n$S(){return this.a.$ti.h(\"~(af<1>)\")}}\nA.jX.prototype={\n$0(){var s,r,q,p=null\ntry{p=this.a.$0()}catch(q){s=A.E(q)\nr=A.R(q)\nA.p6(this.b,s,r)\nreturn}this.b.b2(p)},\n$S:0}\nA.jV.prototype={\n$0(){this.c.a(null)\nthis.b.b2(null)},\n$S:0}\nA.jZ.prototype={\n$2(a,b){var s=this,r=s.a,q=--r.b\nif(r.a!=null){r.a=null\nr.d=a\nr.c=b\nif(q===0||s.c)s.d.W(a,b)}else if(q===0&&!s.c){q=r.d\nq.toString\nr=r.c\nr.toString\ns.d.W(q,r)}},\n$S:6}\nA.jY.prototype={\n$1(a){var s,r,q,p,o,n,m=this,l=m.a,k=--l.b,j=l.a\nif(j!=null){J.px(j,m.b,a)\nif(J.X(k,0)){l=m.d\ns=A.d([],l.h(\"w<0>\"))\nfor(q=j,p=q.length,o=0;o<q.length;q.length===p||(0,A.W)(q),++o){r=q[o]\nn=r\nif(n==null)n=l.a(n)\nJ.on(s,n)}m.c.bq(s)}}else if(J.X(k,0)&&!m.f){s=l.d\ns.toString\nl=l.c\nl.toString\nm.c.W(s,l)}},\n$S(){return this.d.h(\"F(0)\")}}\nA.dp.prototype={\nbx(a,b){var s\nA.aD(a,\"error\",t.K)\nif((this.a.a&30)!==0)throw A.a(A.B(\"Future already completed\"))\ns=$.i.aL(a,b)\nif(s!=null){a=s.a\nb=s.b}else if(b==null)b=A.fD(a)\nthis.W(a,b)},\naK(a){return this.bx(a,null)}}\nA.a2.prototype={\nL(a){var s=this.a\nif((s.a&30)!==0)throw A.a(A.B(\"Future already completed\"))\ns.b1(a)},\naV(){return this.L(null)},\nW(a,b){this.a.aE(a,b)}}\nA.a8.prototype={\nL(a){var s=this.a\nif((s.a&30)!==0)throw A.a(A.B(\"Future already completed\"))\ns.b2(a)},\naV(){return this.L(null)},\nW(a,b){this.a.W(a,b)}}\nA.cc.prototype={\nkg(a){if((this.c&15)!==6)return!0\nreturn this.b.b.bh(this.d,a.a,t.y,t.K)},\nk6(a){var s,r=this.e,q=null,p=t.z,o=t.K,n=a.a,m=this.b.b\nif(t.b.b(r))q=m.eK(r,n,a.b,p,o,t.l)\nelse q=m.bh(r,n,p,o)\ntry{p=q\nreturn p}catch(s){if(t.eK.b(A.E(s))){if((this.c&1)!==0)throw A.a(A.K(\"The error handler of Future.then must return a value of the returned future's type\",\"onError\"))\nthrow A.a(A.K(\"The error handler of Future.catchError must return a value of the future's type\",\"onError\"))}else throw s}}}\nA.k.prototype={\nfH(a){this.a=this.a&1|4\nthis.c=a},\nbG(a,b,c){var s,r,q=$.i\nif(q===B.d){if(b!=null&&!t.b.b(b)&&!t.bI.b(b))throw A.a(A.ag(b,\"onError\",u.c))}else{a=q.be(a,c.h(\"0/\"),this.$ti.c)\nif(b!=null)b=A.wi(b,q)}s=new A.k($.i,c.h(\"k<0>\"))\nr=b==null?1:3\nthis.ct(new A.cc(s,r,a,b,this.$ti.h(\"@<1>\").H(c).h(\"cc<1,2>\")))\nreturn s},\nbF(a,b){return this.bG(a,null,b)},\nfN(a,b,c){var s=new A.k($.i,c.h(\"k<0>\"))\nthis.ct(new A.cc(s,19,a,b,this.$ti.h(\"@<1>\").H(c).h(\"cc<1,2>\")))\nreturn s},\nai(a){var s=this.$ti,r=$.i,q=new A.k(r,s)\nif(r!==B.d)a=r.au(a,t.z)\nthis.ct(new A.cc(q,8,a,null,s.h(\"cc<1,1>\")))\nreturn q},\nj8(a){this.a=this.a&1|16\nthis.c=a},\ncu(a){this.a=a.a&30|this.a&1\nthis.c=a.c},\nct(a){var s=this,r=s.a\nif(r<=3){a.a=s.c\ns.c=a}else{if((r&4)!==0){r=s.c\nif((r.a&24)===0){r.ct(a)\nreturn}s.cu(r)}s.b.b_(new A.mj(s,a))}},\ndY(a){var s,r,q,p,o,n=this,m={}\nm.a=a\nif(a==null)return\ns=n.a\nif(s<=3){r=n.c\nn.c=a\nif(r!=null){q=a.a\nfor(p=a;q!=null;p=q,q=o)o=q.a\np.a=r}}else{if((s&4)!==0){s=n.c\nif((s.a&24)===0){s.dY(a)\nreturn}n.cu(s)}m.a=n.cF(a)\nn.b.b_(new A.mq(m,n))}},\ncE(){var s=this.c\nthis.c=null\nreturn this.cF(s)},\ncF(a){var s,r,q\nfor(s=a,r=null;s!=null;r=s,s=q){q=s.a\ns.a=r}return r},\nf5(a){var s,r,q,p=this\np.a^=2\ntry{a.bG(new A.mn(p),new A.mo(p),t.P)}catch(q){s=A.E(q)\nr=A.R(q)\nA.oh(new A.mp(p,s,r))}},\nb2(a){var s,r=this,q=r.$ti\nif(q.h(\"C<1>\").b(a))if(q.b(a))A.oV(a,r)\nelse r.f5(a)\nelse{s=r.cE()\nr.a=8\nr.c=a\nA.du(r,s)}},\nbq(a){var s=this,r=s.cE()\ns.a=8\ns.c=a\nA.du(s,r)},\nW(a,b){var s=this.cE()\nthis.j8(A.iV(a,b))\nA.du(this,s)},\nb1(a){if(this.$ti.h(\"C<1>\").b(a)){this.f6(a)\nreturn}this.f4(a)},\nf4(a){this.a^=2\nthis.b.b_(new A.ml(this,a))},\nf6(a){if(this.$ti.b(a)){A.v1(a,this)\nreturn}this.f5(a)},\naE(a,b){this.a^=2\nthis.b.b_(new A.mk(this,a,b))},\n$iC:1}\nA.mj.prototype={\n$0(){A.du(this.a,this.b)},\n$S:0}\nA.mq.prototype={\n$0(){A.du(this.b,this.a.a)},\n$S:0}\nA.mn.prototype={\n$1(a){var s,r,q,p=this.a\np.a^=2\ntry{p.bq(p.$ti.c.a(a))}catch(q){s=A.E(q)\nr=A.R(q)\np.W(s,r)}},\n$S:25}\nA.mo.prototype={\n$2(a,b){this.a.W(a,b)},\n$S:80}\nA.mp.prototype={\n$0(){this.a.W(this.b,this.c)},\n$S:0}\nA.mm.prototype={\n$0(){A.oV(this.a.a,this.b)},\n$S:0}\nA.ml.prototype={\n$0(){this.a.bq(this.b)},\n$S:0}\nA.mk.prototype={\n$0(){this.a.W(this.b,this.c)},\n$S:0}\nA.mt.prototype={\n$0(){var s,r,q,p,o,n,m=this,l=null\ntry{q=m.a.a\nl=q.b.b.bg(q.d,t.z)}catch(p){s=A.E(p)\nr=A.R(p)\nq=m.c&&m.b.a.c.a===s\no=m.a\nif(q)o.c=m.b.a.c\nelse o.c=A.iV(s,r)\no.b=!0\nreturn}if(l instanceof A.k&&(l.a&24)!==0){if((l.a&16)!==0){q=m.a\nq.c=l.c\nq.b=!0}return}if(l instanceof A.k){n=m.b.a\nq=m.a\nq.c=l.bF(new A.mu(n),t.z)\nq.b=!1}},\n$S:0}\nA.mu.prototype={\n$1(a){return this.a},\n$S:82}\nA.ms.prototype={\n$0(){var s,r,q,p,o,n\ntry{q=this.a\np=q.a\no=p.$ti\nq.c=p.b.b.bh(p.d,this.b,o.h(\"2/\"),o.c)}catch(n){s=A.E(n)\nr=A.R(n)\nq=this.a\nq.c=A.iV(s,r)\nq.b=!0}},\n$S:0}\nA.mr.prototype={\n$0(){var s,r,q,p,o,n,m=this\ntry{s=m.a.a.c\np=m.b\nif(p.a.kg(s)&&p.a.e!=null){p.c=p.a.k6(s)\np.b=!1}}catch(o){r=A.E(o)\nq=A.R(o)\np=m.a.a.c\nn=m.b\nif(p.a===r)n.c=p\nelse n.c=A.iV(r,q)\nn.b=!0}},\n$S:0}\nA.i0.prototype={}\nA.Y.prototype={\ngl(a){var s={},r=new A.k($.i,t.gR)\ns.a=0\nthis.R(new A.l_(s,this),!0,new A.l0(s,r),r.gdB())\nreturn r},\ngG(a){var s=new A.k($.i,A.t(this).h(\"k<Y.T>\")),r=this.R(null,!0,new A.kY(s),s.gdB())\nr.c9(new A.kZ(this,r,s))\nreturn s},\nk0(a,b){var s=new A.k($.i,A.t(this).h(\"k<Y.T>\")),r=this.R(null,!0,new A.kW(null,s),s.gdB())\nr.c9(new A.kX(this,b,r,s))\nreturn s}}\nA.l_.prototype={\n$1(a){++this.a.a},\n$S(){return A.t(this.b).h(\"~(Y.T)\")}}\nA.l0.prototype={\n$0(){this.b.b2(this.a.a)},\n$S:0}\nA.kY.prototype={\n$0(){var s,r,q,p\ntry{q=A.ak()\nthrow A.a(q)}catch(p){s=A.E(p)\nr=A.R(p)\nA.p6(this.a,s,r)}},\n$S:0}\nA.kZ.prototype={\n$1(a){A.r8(this.b,this.c,a)},\n$S(){return A.t(this.a).h(\"~(Y.T)\")}}\nA.kW.prototype={\n$0(){var s,r,q,p\ntry{q=A.ak()\nthrow A.a(q)}catch(p){s=A.E(p)\nr=A.R(p)\nA.p6(this.b,s,r)}},\n$S:0}\nA.kX.prototype={\n$1(a){var s=this.c,r=this.d\nA.wo(new A.kU(this.b,a),new A.kV(s,r,a),A.vL(s,r))},\n$S(){return A.t(this.a).h(\"~(Y.T)\")}}\nA.kU.prototype={\n$0(){return this.a.$1(this.b)},\n$S:22}\nA.kV.prototype={\n$1(a){if(a)A.r8(this.a,this.b,this.c)},\n$S:39}\nA.hD.prototype={}\nA.cI.prototype={\ngiM(){if((this.b&8)===0)return this.a\nreturn this.a.ge6()},\ndH(){var s,r=this\nif((r.b&8)===0){s=r.a\nreturn s==null?r.a=new A.f5():s}s=r.a.ge6()\nreturn s},\ngaT(){var s=this.a\nreturn(this.b&8)!==0?s.ge6():s},\nds(){if((this.b&4)!==0)return new A.b2(\"Cannot add event after closing\")\nreturn new A.b2(\"Cannot add event while adding a stream\")},\nfc(){var s=this.c\nif(s==null)s=this.c=(this.b&2)!==0?$.ci():new A.k($.i,t.D)\nreturn s},\nv(a,b){var s=this,r=s.b\nif(r>=4)throw A.a(s.ds())\nif((r&1)!==0)s.b3(b)\nelse if((r&3)===0)s.dH().v(0,new A.dq(b))},\na3(a,b){var s,r,q=this\nA.aD(a,\"error\",t.K)\nif(q.b>=4)throw A.a(q.ds())\ns=$.i.aL(a,b)\nif(s!=null){a=s.a\nb=s.b}else if(b==null)b=A.fD(a)\nr=q.b\nif((r&1)!==0)q.b5(a,b)\nelse if((r&3)===0)q.dH().v(0,new A.eQ(a,b))},\njz(a){return this.a3(a,null)},\np(){var s=this,r=s.b\nif((r&4)!==0)return s.fc()\nif(r>=4)throw A.a(s.ds())\nr=s.b=r|4\nif((r&1)!==0)s.b4()\nelse if((r&3)===0)s.dH().v(0,B.y)\nreturn s.fc()},\nfK(a,b,c,d){var s,r,q,p,o=this\nif((o.b&3)!==0)throw A.a(A.B(\"Stream has already been listened to.\"))\ns=A.v_(o,a,b,c,d,A.t(o).c)\nr=o.giM()\nq=o.b|=1\nif((q&8)!==0){p=o.a\np.se6(s)\np.bf()}else o.a=s\ns.j9(r)\ns.dL(new A.nq(o))\nreturn s},\nfu(a){var s,r,q,p,o,n,m,l=this,k=null\nif((l.b&8)!==0)k=l.a.J()\nl.a=null\nl.b=l.b&4294967286|2\ns=l.r\nif(s!=null)if(k==null)try{r=s.$0()\nif(r instanceof A.k)k=r}catch(o){q=A.E(o)\np=A.R(o)\nn=new A.k($.i,t.D)\nn.aE(q,p)\nk=n}else k=k.ai(s)\nm=new A.np(l)\nif(k!=null)k=k.ai(m)\nelse m.$0()\nreturn k},\nfv(a){if((this.b&8)!==0)this.a.bB()\nA.iM(this.e)},\nfw(a){if((this.b&8)!==0)this.a.bf()\nA.iM(this.f)},\n$ia9:1}\nA.nq.prototype={\n$0(){A.iM(this.a.d)},\n$S:0}\nA.np.prototype={\n$0(){var s=this.a.c\nif(s!=null&&(s.a&30)===0)s.b1(null)},\n$S:0}\nA.iC.prototype={\nb3(a){this.gaT().bp(a)},\nb5(a,b){this.gaT().bn(a,b)},\nb4(){this.gaT().cv()}}\nA.i1.prototype={\nb3(a){this.gaT().bo(new A.dq(a))},\nb5(a,b){this.gaT().bo(new A.eQ(a,b))},\nb4(){this.gaT().bo(B.y)}}\nA.dn.prototype={}\nA.dK.prototype={}\nA.an.prototype={\ngB(a){return(A.ev(this.a)^892482866)>>>0},\nO(a,b){if(b==null)return!1\nif(this===b)return!0\nreturn b instanceof A.an&&b.a===this.a}}\nA.cb.prototype={\ncB(){return this.w.fu(this)},\nal(){this.w.fv(this)},\nam(){this.w.fw(this)}}\nA.dH.prototype={\nv(a,b){this.a.v(0,b)},\na3(a,b){this.a.a3(a,b)},\np(){return this.a.p()},\n$ia9:1}\nA.af.prototype={\nj9(a){var s=this\nif(a==null)return\ns.r=a\nif(a.c!=null){s.e=(s.e|128)>>>0\na.cp(s)}},\nc9(a){this.a=A.i5(this.d,a,A.t(this).h(\"af.T\"))},\neF(a){var s=this\ns.e=(s.e&4294967263)>>>0\ns.b=A.i6(s.d,a)},\nbB(){var s,r,q=this,p=q.e\nif((p&8)!==0)return\ns=(p+256|4)>>>0\nq.e=s\nif(p<256){r=q.r\nif(r!=null)if(r.a===1)r.a=3}if((p&4)===0&&(s&64)===0)q.dL(q.gbN())},\nbf(){var s=this,r=s.e\nif((r&8)!==0)return\nif(r>=256){r=s.e=r-256\nif(r<256)if((r&128)!==0&&s.r.c!=null)s.r.cp(s)\nelse{r=(r&4294967291)>>>0\ns.e=r\nif((r&64)===0)s.dL(s.gbO())}}},\nJ(){var s=this,r=(s.e&4294967279)>>>0\ns.e=r\nif((r&8)===0)s.dv()\nr=s.f\nreturn r==null?$.ci():r},\ndv(){var s,r=this,q=r.e=(r.e|8)>>>0\nif((q&128)!==0){s=r.r\nif(s.a===1)s.a=3}if((q&64)===0)r.r=null\nr.f=r.cB()},\nbp(a){var s=this.e\nif((s&8)!==0)return\nif(s<64)this.b3(a)\nelse this.bo(new A.dq(a))},\nbn(a,b){var s=this.e\nif((s&8)!==0)return\nif(s<64)this.b5(a,b)\nelse this.bo(new A.eQ(a,b))},\ncv(){var s=this,r=s.e\nif((r&8)!==0)return\nr=(r|2)>>>0\ns.e=r\nif(r<64)s.b4()\nelse s.bo(B.y)},\nal(){},\nam(){},\ncB(){return null},\nbo(a){var s,r=this,q=r.r\nif(q==null)q=r.r=new A.f5()\nq.v(0,a)\ns=r.e\nif((s&128)===0){s=(s|128)>>>0\nr.e=s\nif(s<256)q.cp(r)}},\nb3(a){var s=this,r=s.e\ns.e=(r|64)>>>0\ns.d.ci(s.a,a,A.t(s).h(\"af.T\"))\ns.e=(s.e&4294967231)>>>0\ns.dw((r&4)!==0)},\nb5(a,b){var s,r=this,q=r.e,p=new A.m2(r,a,b)\nif((q&1)!==0){r.e=(q|16)>>>0\nr.dv()\ns=r.f\nif(s!=null&&s!==$.ci())s.ai(p)\nelse p.$0()}else{p.$0()\nr.dw((q&4)!==0)}},\nb4(){var s,r=this,q=new A.m1(r)\nr.dv()\nr.e=(r.e|16)>>>0\ns=r.f\nif(s!=null&&s!==$.ci())s.ai(q)\nelse q.$0()},\ndL(a){var s=this,r=s.e\ns.e=(r|64)>>>0\na.$0()\ns.e=(s.e&4294967231)>>>0\ns.dw((r&4)!==0)},\ndw(a){var s,r,q=this,p=q.e\nif((p&128)!==0&&q.r.c==null){p=q.e=(p&4294967167)>>>0\ns=!1\nif((p&4)!==0)if(p<256){s=q.r\ns=s==null?null:s.c==null\ns=s!==!1}if(s){p=(p&4294967291)>>>0\nq.e=p}}for(;!0;a=r){if((p&8)!==0){q.r=null\nreturn}r=(p&4)!==0\nif(a===r)break\nq.e=(p^64)>>>0\nif(r)q.al()\nelse q.am()\np=(q.e&4294967231)>>>0\nq.e=p}if((p&128)!==0&&p<256)q.r.cp(q)}}\nA.m2.prototype={\n$0(){var s,r,q,p=this.a,o=p.e\nif((o&8)!==0&&(o&16)===0)return\np.e=(o|64)>>>0\ns=p.b\no=this.b\nr=t.K\nq=p.d\nif(t.da.b(s))q.hn(s,o,this.c,r,t.l)\nelse q.ci(s,o,r)\np.e=(p.e&4294967231)>>>0},\n$S:0}\nA.m1.prototype={\n$0(){var s=this.a,r=s.e\nif((r&16)===0)return\ns.e=(r|74)>>>0\ns.d.cg(s.c)\ns.e=(s.e&4294967231)>>>0},\n$S:0}\nA.dF.prototype={\nR(a,b,c,d){return this.a.fK(a,d,c,b===!0)},\naX(a,b,c){return this.R(a,null,b,c)},\nkf(a){return this.R(a,null,null,null)},\neB(a,b){return this.R(a,null,b,null)}}\nA.ia.prototype={\ngc8(){return this.a},\nsc8(a){return this.a=a}}\nA.dq.prototype={\neH(a){a.b3(this.b)}}\nA.eQ.prototype={\neH(a){a.b5(this.b,this.c)}}\nA.mc.prototype={\neH(a){a.b4()},\ngc8(){return null},\nsc8(a){throw A.a(A.B(\"No events after a done.\"))}}\nA.f5.prototype={\ncp(a){var s=this,r=s.a\nif(r===1)return\nif(r>=1){s.a=1\nreturn}A.oh(new A.nf(s,a))\ns.a=1},\nv(a,b){var s=this,r=s.c\nif(r==null)s.b=s.c=b\nelse{r.sc8(b)\ns.c=b}}}\nA.nf.prototype={\n$0(){var s,r,q=this.a,p=q.a\nq.a=0\nif(p===3)return\ns=q.b\nr=s.gc8()\nq.b=r\nif(r==null)q.c=null\ns.eH(this.b)},\n$S:0}\nA.eR.prototype={\nc9(a){},\neF(a){},\nbB(){var s=this.a\nif(s>=0)this.a=s+2},\nbf(){var s=this,r=s.a-2\nif(r<0)return\nif(r===0){s.a=1\nA.oh(s.gfs())}else s.a=r},\nJ(){this.a=-1\nthis.c=null\nreturn $.ci()},\niI(){var s,r=this,q=r.a-1\nif(q===0){r.a=-1\ns=r.c\nif(s!=null){r.c=null\nr.b.cg(s)}}else r.a=q}}\nA.dG.prototype={\ngm(){if(this.c)return this.b\nreturn null},\nk(){var s,r=this,q=r.a\nif(q!=null){if(r.c){s=new A.k($.i,t.k)\nr.b=s\nr.c=!1\nq.bf()\nreturn s}throw A.a(A.B(\"Already waiting for next.\"))}return r.it()},\nit(){var s,r,q=this,p=q.b\nif(p!=null){s=new A.k($.i,t.k)\nq.b=s\nr=p.R(q.giC(),!0,q.giE(),q.giG())\nif(q.b!=null)q.a=r\nreturn s}return $.rS()},\nJ(){var s=this,r=s.a,q=s.b\ns.b=null\nif(r!=null){s.a=null\nif(!s.c)q.b1(!1)\nelse s.c=!1\nreturn r.J()}return $.ci()},\niD(a){var s,r,q=this\nif(q.a==null)return\ns=q.b\nq.b=a\nq.c=!0\ns.b2(!0)\nif(q.c){r=q.a\nif(r!=null)r.bB()}},\niH(a,b){var s=this,r=s.a,q=s.b\ns.b=s.a=null\nif(r!=null)q.W(a,b)\nelse q.aE(a,b)},\niF(){var s=this,r=s.a,q=s.b\ns.b=s.a=null\nif(r!=null)q.bq(!1)\nelse q.f4(!1)}}\nA.nL.prototype={\n$0(){return this.a.W(this.b,this.c)},\n$S:0}\nA.nK.prototype={\n$2(a,b){A.vK(this.a,this.b,a,b)},\n$S:6}\nA.nM.prototype={\n$0(){return this.a.b2(this.b)},\n$S:0}\nA.eW.prototype={\nR(a,b,c,d){var s=this.$ti,r=$.i,q=b===!0?1:0,p=d!=null?32:0,o=A.i5(r,a,s.y[1]),n=A.i6(r,d)\ns=new A.ds(this,o,n,r.au(c,t.H),r,q|p,s.h(\"ds<1,2>\"))\ns.x=this.a.aX(s.gdM(),s.gdO(),s.gdQ())\nreturn s},\naX(a,b,c){return this.R(a,null,b,c)}}\nA.ds.prototype={\nbp(a){if((this.e&2)!==0)return\nthis.dm(a)},\nbn(a,b){if((this.e&2)!==0)return\nthis.bm(a,b)},\nal(){var s=this.x\nif(s!=null)s.bB()},\nam(){var s=this.x\nif(s!=null)s.bf()},\ncB(){var s=this.x\nif(s!=null){this.x=null\nreturn s.J()}return null},\ndN(a){this.w.im(a,this)},\ndR(a,b){this.bn(a,b)},\ndP(){this.cv()}}\nA.f0.prototype={\nim(a,b){var s,r,q,p,o,n,m=null\ntry{m=this.b.$1(a)}catch(q){s=A.E(q)\nr=A.R(q)\np=s\no=r\nn=$.i.aL(p,o)\nif(n!=null){p=n.a\no=n.b}b.bn(p,o)\nreturn}b.bp(m)}}\nA.eT.prototype={\nv(a,b){var s=this.a\nif((s.e&2)!==0)A.y(A.B(\"Stream is already closed\"))\ns.dm(b)},\na3(a,b){var s=this.a\nif((s.e&2)!==0)A.y(A.B(\"Stream is already closed\"))\ns.bm(a,b)},\np(){var s=this.a\nif((s.e&2)!==0)A.y(A.B(\"Stream is already closed\"))\ns.eW()},\n$ia9:1}\nA.dD.prototype={\nal(){var s=this.x\nif(s!=null)s.bB()},\nam(){var s=this.x\nif(s!=null)s.bf()},\ncB(){var s=this.x\nif(s!=null){this.x=null\nreturn s.J()}return null},\ndN(a){var s,r,q,p\ntry{q=this.w\nq===$&&A.G()\nq.v(0,a)}catch(p){s=A.E(p)\nr=A.R(p)\nif((this.e&2)!==0)A.y(A.B(\"Stream is already closed\"))\nthis.bm(s,r)}},\ndR(a,b){var s,r,q,p,o=this,n=\"Stream is already closed\"\ntry{q=o.w\nq===$&&A.G()\nq.a3(a,b)}catch(p){s=A.E(p)\nr=A.R(p)\nif(s===a){if((o.e&2)!==0)A.y(A.B(n))\no.bm(a,b)}else{if((o.e&2)!==0)A.y(A.B(n))\no.bm(s,r)}}},\ndP(){var s,r,q,p,o=this\ntry{o.x=null\nq=o.w\nq===$&&A.G()\nq.p()}catch(p){s=A.E(p)\nr=A.R(p)\nif((o.e&2)!==0)A.y(A.B(\"Stream is already closed\"))\no.bm(s,r)}}}\nA.fc.prototype={\nee(a){return new A.eL(this.a,a,this.$ti.h(\"eL<1,2>\"))}}\nA.eL.prototype={\nR(a,b,c,d){var s=this.$ti,r=$.i,q=b===!0?1:0,p=d!=null?32:0,o=A.i5(r,a,s.y[1]),n=A.i6(r,d),m=new A.dD(o,n,r.au(c,t.H),r,q|p,s.h(\"dD<1,2>\"))\nm.w=this.a.$1(new A.eT(m))\nm.x=this.b.aX(m.gdM(),m.gdO(),m.gdQ())\nreturn m},\naX(a,b,c){return this.R(a,null,b,c)}}\nA.dv.prototype={\nv(a,b){var s,r=this.d\nif(r==null)throw A.a(A.B(\"Sink is closed\"))\nthis.$ti.y[1].a(b)\ns=r.a\nif((s.e&2)!==0)A.y(A.B(\"Stream is already closed\"))\ns.dm(b)},\na3(a,b){var s\nA.aD(a,\"error\",t.K)\ns=this.d\nif(s==null)throw A.a(A.B(\"Sink is closed\"))\ns.a3(a,b)},\np(){var s=this.d\nif(s==null)return\nthis.d=null\nthis.c.$1(s)},\n$ia9:1}\nA.dE.prototype={\nee(a){return this.hJ(a)}}\nA.nr.prototype={\n$1(a){var s=this\nreturn new A.dv(s.a,s.b,s.c,a,s.e.h(\"@<0>\").H(s.d).h(\"dv<1,2>\"))},\n$S(){return this.e.h(\"@<0>\").H(this.d).h(\"dv<1,2>(a9<2>)\")}}\nA.au.prototype={}\nA.iI.prototype={$ioO:1}\nA.dM.prototype={$iZ:1}\nA.iH.prototype={\nbP(a,b,c){var s,r,q,p,o,n,m,l,k=this.gdS(),j=k.a\nif(j===B.d){A.fq(b,c)\nreturn}s=k.b\nr=j.ga1()\nm=j.ghe()\nm.toString\nq=m\np=$.i\ntry{$.i=q\ns.$5(j,r,a,b,c)\n$.i=p}catch(l){o=A.E(l)\nn=A.R(l)\n$.i=p\nm=b===o?c:n\nq.bP(j,o,m)}},\n$ix:1}\nA.i7.prototype={\ngf3(){var s=this.at\nreturn s==null?this.at=new A.dM(this):s},\nga1(){return this.ax.gf3()},\ngbb(){return this.as.a},\ncg(a){var s,r,q\ntry{this.bg(a,t.H)}catch(q){s=A.E(q)\nr=A.R(q)\nthis.bP(this,s,r)}},\nci(a,b,c){var s,r,q\ntry{this.bh(a,b,t.H,c)}catch(q){s=A.E(q)\nr=A.R(q)\nthis.bP(this,s,r)}},\nhn(a,b,c,d,e){var s,r,q\ntry{this.eK(a,b,c,t.H,d,e)}catch(q){s=A.E(q)\nr=A.R(q)\nthis.bP(this,s,r)}},\nef(a,b){return new A.m9(this,this.au(a,b),b)},\nfU(a,b,c){return new A.mb(this,this.be(a,b,c),c,b)},\ncQ(a){return new A.m8(this,this.au(a,t.H))},\neg(a,b){return new A.ma(this,this.be(a,t.H,b),b)},\ni(a,b){var s,r=this.ay,q=r.i(0,b)\nif(q!=null||r.a4(b))return q\ns=this.ax.i(0,b)\nif(s!=null)r.q(0,b,s)\nreturn s},\nc4(a,b){this.bP(this,a,b)},\nh4(a,b){var s=this.Q,r=s.a\nreturn s.b.$5(r,r.ga1(),this,a,b)},\nbg(a){var s=this.a,r=s.a\nreturn s.b.$4(r,r.ga1(),this,a)},\nbh(a,b){var s=this.b,r=s.a\nreturn s.b.$5(r,r.ga1(),this,a,b)},\neK(a,b,c){var s=this.c,r=s.a\nreturn s.b.$6(r,r.ga1(),this,a,b,c)},\nau(a){var s=this.d,r=s.a\nreturn s.b.$4(r,r.ga1(),this,a)},\nbe(a){var s=this.e,r=s.a\nreturn s.b.$4(r,r.ga1(),this,a)},\nd5(a){var s=this.f,r=s.a\nreturn s.b.$4(r,r.ga1(),this,a)},\naL(a,b){var s,r\nA.aD(a,\"error\",t.K)\ns=this.r\nr=s.a\nif(r===B.d)return null\nreturn s.b.$5(r,r.ga1(),this,a,b)},\nb_(a){var s=this.w,r=s.a\nreturn s.b.$4(r,r.ga1(),this,a)},\nei(a,b){var s=this.x,r=s.a\nreturn s.b.$5(r,r.ga1(),this,a,b)},\nhf(a){var s=this.z,r=s.a\nreturn s.b.$4(r,r.ga1(),this,a)},\ngfE(){return this.a},\ngfG(){return this.b},\ngfF(){return this.c},\ngfA(){return this.d},\ngfB(){return this.e},\ngfz(){return this.f},\ngfd(){return this.r},\nge1(){return this.w},\ngfa(){return this.x},\ngf9(){return this.y},\ngft(){return this.z},\ngfg(){return this.Q},\ngdS(){return this.as},\nghe(){return this.ax},\ngfm(){return this.ay}}\nA.m9.prototype={\n$0(){return this.a.bg(this.b,this.c)},\n$S(){return this.c.h(\"0()\")}}\nA.mb.prototype={\n$1(a){var s=this\nreturn s.a.bh(s.b,a,s.d,s.c)},\n$S(){return this.d.h(\"@<0>\").H(this.c).h(\"1(2)\")}}\nA.m8.prototype={\n$0(){return this.a.cg(this.b)},\n$S:0}\nA.ma.prototype={\n$1(a){return this.a.ci(this.b,a,this.c)},\n$S(){return this.c.h(\"~(0)\")}}\nA.nS.prototype={\n$0(){A.pM(this.a,this.b)},\n$S:0}\nA.iw.prototype={\ngfE(){return B.bC},\ngfG(){return B.bE},\ngfF(){return B.bD},\ngfA(){return B.bB},\ngfB(){return B.bw},\ngfz(){return B.bH},\ngfd(){return B.by},\nge1(){return B.bF},\ngfa(){return B.bx},\ngf9(){return B.bG},\ngft(){return B.bA},\ngfg(){return B.bz},\ngdS(){return B.bv},\nghe(){return null},\ngfm(){return $.t8()},\ngf3(){var s=$.ni\nreturn s==null?$.ni=new A.dM(this):s},\nga1(){var s=$.ni\nreturn s==null?$.ni=new A.dM(this):s},\ngbb(){return this},\ncg(a){var s,r,q\ntry{if(B.d===$.i){a.$0()\nreturn}A.nT(null,null,this,a)}catch(q){s=A.E(q)\nr=A.R(q)\nA.fq(s,r)}},\nci(a,b){var s,r,q\ntry{if(B.d===$.i){a.$1(b)\nreturn}A.nV(null,null,this,a,b)}catch(q){s=A.E(q)\nr=A.R(q)\nA.fq(s,r)}},\nhn(a,b,c){var s,r,q\ntry{if(B.d===$.i){a.$2(b,c)\nreturn}A.nU(null,null,this,a,b,c)}catch(q){s=A.E(q)\nr=A.R(q)\nA.fq(s,r)}},\nef(a,b){return new A.nk(this,a,b)},\nfU(a,b,c){return new A.nm(this,a,c,b)},\ncQ(a){return new A.nj(this,a)},\neg(a,b){return new A.nl(this,a,b)},\ni(a,b){return null},\nc4(a,b){A.fq(a,b)},\nh4(a,b){return A.rk(null,null,this,a,b)},\nbg(a){if($.i===B.d)return a.$0()\nreturn A.nT(null,null,this,a)},\nbh(a,b){if($.i===B.d)return a.$1(b)\nreturn A.nV(null,null,this,a,b)},\neK(a,b,c){if($.i===B.d)return a.$2(b,c)\nreturn A.nU(null,null,this,a,b,c)},\nau(a){return a},\nbe(a){return a},\nd5(a){return a},\naL(a,b){return null},\nb_(a){A.nW(null,null,this,a)},\nei(a,b){return A.oK(a,b)},\nhf(a){A.pn(a)}}\nA.nk.prototype={\n$0(){return this.a.bg(this.b,this.c)},\n$S(){return this.c.h(\"0()\")}}\nA.nm.prototype={\n$1(a){var s=this\nreturn s.a.bh(s.b,a,s.d,s.c)},\n$S(){return this.d.h(\"@<0>\").H(this.c).h(\"1(2)\")}}\nA.nj.prototype={\n$0(){return this.a.cg(this.b)},\n$S:0}\nA.nl.prototype={\n$1(a){return this.a.ci(this.b,a,this.c)},\n$S(){return this.c.h(\"~(0)\")}}\nA.cE.prototype={\ngl(a){return this.a},\ngF(a){return this.a===0},\nga_(){return new A.cF(this,A.t(this).h(\"cF<1>\"))},\ngaP(){var s=A.t(this)\nreturn A.en(new A.cF(this,s.h(\"cF<1>\")),new A.mv(this),s.c,s.y[1])},\na4(a){var s,r\nif(typeof a==\"string\"&&a!==\"__proto__\"){s=this.b\nreturn s==null?!1:s[a]!=null}else if(typeof a==\"number\"&&(a&1073741823)===a){r=this.c\nreturn r==null?!1:r[a]!=null}else return this.i4(a)},\ni4(a){var s=this.d\nif(s==null)return!1\nreturn this.aR(this.fh(s,a),a)>=0},\ni(a,b){var s,r,q\nif(typeof b==\"string\"&&b!==\"__proto__\"){s=this.b\nr=s==null?null:A.qH(s,b)\nreturn r}else if(typeof b==\"number\"&&(b&1073741823)===b){q=this.c\nr=q==null?null:A.qH(q,b)\nreturn r}else return this.ik(b)},\nik(a){var s,r,q=this.d\nif(q==null)return null\ns=this.fh(q,a)\nr=this.aR(s,a)\nreturn r<0?null:s[r+1]},\nq(a,b,c){var s,r,q=this\nif(typeof b==\"string\"&&b!==\"__proto__\"){s=q.b\nq.f1(s==null?q.b=A.oW():s,b,c)}else if(typeof b==\"number\"&&(b&1073741823)===b){r=q.c\nq.f1(r==null?q.c=A.oW():r,b,c)}else q.j7(b,c)},\nj7(a,b){var s,r,q,p=this,o=p.d\nif(o==null)o=p.d=A.oW()\ns=p.dC(a)\nr=o[s]\nif(r==null){A.oX(o,s,[a,b]);++p.a\np.e=null}else{q=p.aR(r,a)\nif(q>=0)r[q+1]=b\nelse{r.push(a,b);++p.a\np.e=null}}},\naa(a,b){var s,r,q,p,o,n=this,m=n.f8()\nfor(s=m.length,r=A.t(n).y[1],q=0;q<s;++q){p=m[q]\no=n.i(0,p)\nb.$2(p,o==null?r.a(o):o)\nif(m!==n.e)throw A.a(A.ax(n))}},\nf8(){var s,r,q,p,o,n,m,l,k,j,i=this,h=i.e\nif(h!=null)return h\nh=A.b_(i.a,null,!1,t.z)\ns=i.b\nr=0\nif(s!=null){q=Object.getOwnPropertyNames(s)\np=q.length\nfor(o=0;o<p;++o){h[r]=q[o];++r}}n=i.c\nif(n!=null){q=Object.getOwnPropertyNames(n)\np=q.length\nfor(o=0;o<p;++o){h[r]=+q[o];++r}}m=i.d\nif(m!=null){q=Object.getOwnPropertyNames(m)\np=q.length\nfor(o=0;o<p;++o){l=m[q[o]]\nk=l.length\nfor(j=0;j<k;j+=2){h[r]=l[j];++r}}}return i.e=h},\nf1(a,b,c){if(a[b]==null){++this.a\nthis.e=null}A.oX(a,b,c)},\ndC(a){return J.aw(a)&1073741823},\nfh(a,b){return a[this.dC(b)]},\naR(a,b){var s,r\nif(a==null)return-1\ns=a.length\nfor(r=0;r<s;r+=2)if(J.X(a[r],b))return r\nreturn-1}}\nA.mv.prototype={\n$1(a){var s=this.a,r=s.i(0,a)\nreturn r==null?A.t(s).y[1].a(r):r},\n$S(){return A.t(this.a).h(\"2(1)\")}}\nA.dw.prototype={\ndC(a){return A.pm(a)&1073741823},\naR(a,b){var s,r,q\nif(a==null)return-1\ns=a.length\nfor(r=0;r<s;r+=2){q=a[r]\nif(q==null?b==null:q===b)return r}return-1}}\nA.cF.prototype={\ngl(a){return this.a.a},\ngF(a){return this.a.a===0},\ngt(a){var s=this.a\nreturn new A.ih(s,s.f8(),this.$ti.h(\"ih<1>\"))}}\nA.ih.prototype={\ngm(){var s=this.d\nreturn s==null?this.$ti.c.a(s):s},\nk(){var s=this,r=s.b,q=s.c,p=s.a\nif(r!==p.e)throw A.a(A.ax(p))\nelse if(q>=r.length){s.d=null\nreturn!1}else{s.d=r[q]\ns.c=q+1\nreturn!0}}}\nA.eZ.prototype={\ngt(a){var s=this,r=new A.dy(s,s.r,s.$ti.h(\"dy<1>\"))\nr.c=s.e\nreturn r},\ngl(a){return this.a},\ngF(a){return this.a===0},\nM(a,b){var s,r\nif(b!==\"__proto__\"){s=this.b\nif(s==null)return!1\nreturn s[b]!=null}else{r=this.i3(b)\nreturn r}},\ni3(a){var s=this.d\nif(s==null)return!1\nreturn this.aR(s[B.a.gB(a)&1073741823],a)>=0},\ngG(a){var s=this.e\nif(s==null)throw A.a(A.B(\"No elements\"))\nreturn s.a},\ngC(a){var s=this.f\nif(s==null)throw A.a(A.B(\"No elements\"))\nreturn s.a},\nv(a,b){var s,r,q=this\nif(typeof b==\"string\"&&b!==\"__proto__\"){s=q.b\nreturn q.f0(s==null?q.b=A.oY():s,b)}else if(typeof b==\"number\"&&(b&1073741823)===b){r=q.c\nreturn q.f0(r==null?q.c=A.oY():r,b)}else return q.hT(b)},\nhT(a){var s,r,q=this,p=q.d\nif(p==null)p=q.d=A.oY()\ns=J.aw(a)&1073741823\nr=p[s]\nif(r==null)p[s]=[q.dX(a)]\nelse{if(q.aR(r,a)>=0)return!1\nr.push(q.dX(a))}return!0},\nA(a,b){var s\nif(typeof b==\"string\"&&b!==\"__proto__\")return this.iV(this.b,b)\nelse{s=this.iU(b)\nreturn s}},\niU(a){var s,r,q,p,o=this.d\nif(o==null)return!1\ns=J.aw(a)&1073741823\nr=o[s]\nq=this.aR(r,a)\nif(q<0)return!1\np=r.splice(q,1)[0]\nif(0===r.length)delete o[s]\nthis.fR(p)\nreturn!0},\nf0(a,b){if(a[b]!=null)return!1\na[b]=this.dX(b)\nreturn!0},\niV(a,b){var s\nif(a==null)return!1\ns=a[b]\nif(s==null)return!1\nthis.fR(s)\ndelete a[b]\nreturn!0},\nfo(){this.r=this.r+1&1073741823},\ndX(a){var s,r=this,q=new A.ne(a)\nif(r.e==null)r.e=r.f=q\nelse{s=r.f\ns.toString\nq.c=s\nr.f=s.b=q}++r.a\nr.fo()\nreturn q},\nfR(a){var s=this,r=a.c,q=a.b\nif(r==null)s.e=q\nelse r.b=q\nif(q==null)s.f=r\nelse q.c=r;--s.a\ns.fo()},\naR(a,b){var s,r\nif(a==null)return-1\ns=a.length\nfor(r=0;r<s;++r)if(J.X(a[r].a,b))return r\nreturn-1}}\nA.ne.prototype={}\nA.dy.prototype={\ngm(){var s=this.d\nreturn s==null?this.$ti.c.a(s):s},\nk(){var s=this,r=s.c,q=s.a\nif(s.b!==q.r)throw A.a(A.ax(q))\nelse if(r==null){s.d=null\nreturn!1}else{s.d=r.a\ns.c=r.b\nreturn!0}}}\nA.k1.prototype={\n$2(a,b){this.a.q(0,this.b.a(a),this.c.a(b))},\n$S:50}\nA.em.prototype={\nA(a,b){if(b.a!==this)return!1\nthis.e4(b)\nreturn!0},\ngt(a){var s=this\nreturn new A.io(s,s.a,s.c,s.$ti.h(\"io<1>\"))},\ngl(a){return this.b},\ngG(a){var s\nif(this.b===0)throw A.a(A.B(\"No such element\"))\ns=this.c\ns.toString\nreturn s},\ngC(a){var s\nif(this.b===0)throw A.a(A.B(\"No such element\"))\ns=this.c.c\ns.toString\nreturn s},\ngF(a){return this.b===0},\ndT(a,b,c){var s,r,q=this\nif(b.a!=null)throw A.a(A.B(\"LinkedListEntry is already in a LinkedList\"));++q.a\nb.a=q\ns=q.b\nif(s===0){b.b=b\nq.c=b.c=b\nq.b=s+1\nreturn}r=a.c\nr.toString\nb.c=r\nb.b=a\na.c=r.b=b\nq.b=s+1},\ne4(a){var s,r,q=this;++q.a\ns=a.b\ns.c=a.c\na.c.b=s\nr=--q.b\na.a=a.b=a.c=null\nif(r===0)q.c=null\nelse if(a===q.c)q.c=s}}\nA.io.prototype={\ngm(){var s=this.c\nreturn s==null?this.$ti.c.a(s):s},\nk(){var s=this,r=s.a\nif(s.b!==r.a)throw A.a(A.ax(s))\nif(r.b!==0)r=s.e&&s.d===r.gG(0)\nelse r=!0\nif(r){s.c=null\nreturn!1}s.e=!0\nr=s.d\ns.c=r\ns.d=r.b\nreturn!0}}\nA.aF.prototype={\ngcc(){var s=this.a\nif(s==null||this===s.gG(0))return null\nreturn this.c}}\nA.z.prototype={\ngt(a){return new A.aZ(a,this.gl(a),A.aE(a).h(\"aZ<z.E>\"))},\nN(a,b){return this.i(a,b)},\ngF(a){return this.gl(a)===0},\ngG(a){if(this.gl(a)===0)throw A.a(A.ak())\nreturn this.i(a,0)},\ngC(a){if(this.gl(a)===0)throw A.a(A.ak())\nreturn this.i(a,this.gl(a)-1)},\nbd(a,b,c){return new A.D(a,b,A.aE(a).h(\"@<z.E>\").H(c).h(\"D<1,2>\"))},\nX(a,b){return A.b3(a,b,null,A.aE(a).h(\"z.E\"))},\nah(a,b){return A.b3(a,0,A.aD(b,\"count\",t.S),A.aE(a).h(\"z.E\"))},\naz(a,b){var s,r,q,p,o=this\nif(o.gF(a)){s=J.pW(0,A.aE(a).h(\"z.E\"))\nreturn s}r=o.i(a,0)\nq=A.b_(o.gl(a),r,!0,A.aE(a).h(\"z.E\"))\nfor(p=1;p<o.gl(a);++p)q[p]=o.i(a,p)\nreturn q},\ncj(a){return this.az(a,!0)},\nb8(a,b){return new A.ah(a,A.aE(a).h(\"@<z.E>\").H(b).h(\"ah<1,2>\"))},\na0(a,b,c){var s=this.gl(a)\nA.b9(b,c,s)\nreturn A.pZ(this.co(a,b,c),!0,A.aE(a).h(\"z.E\"))},\nco(a,b,c){A.b9(b,c,this.gl(a))\nreturn A.b3(a,b,c,A.aE(a).h(\"z.E\"))},\nen(a,b,c,d){var s\nA.b9(b,c,this.gl(a))\nfor(s=b;s<c;++s)this.q(a,s,d)},\nZ(a,b,c,d,e){var s,r,q,p,o\nA.b9(b,c,this.gl(a))\ns=c-b\nif(s===0)return\nA.ab(e,\"skipCount\")\nif(A.aE(a).h(\"q<z.E>\").b(d)){r=e\nq=d}else{q=J.dZ(d,e).az(0,!1)\nr=0}p=J.V(q)\nif(r+s>p.gl(q))throw A.a(A.pT())\nif(r<b)for(o=s-1;o>=0;--o)this.q(a,b+o,p.i(q,r+o))\nelse for(o=0;o<s;++o)this.q(a,b+o,p.i(q,r+o))},\naj(a,b,c,d){return this.Z(a,b,c,d,0)},\naD(a,b,c){var s,r\nif(t.j.b(c))this.aj(a,b,b+c.length,c)\nelse for(s=J.M(c);s.k();b=r){r=b+1\nthis.q(a,b,s.gm())}},\nj(a){return A.ox(a,\"[\",\"]\")},\n$iv:1,\n$if:1,\n$iq:1}\nA.T.prototype={\naa(a,b){var s,r,q,p\nfor(s=J.M(this.ga_()),r=A.t(this).h(\"T.V\");s.k();){q=s.gm()\np=this.i(0,q)\nb.$2(q,p==null?r.a(p):p)}},\ngel(){return J.cQ(this.ga_(),new A.ki(this),A.t(this).h(\"bv<T.K,T.V>\"))},\ngl(a){return J.ae(this.ga_())},\ngF(a){return J.iR(this.ga_())},\ngaP(){return new A.f_(this,A.t(this).h(\"f_<T.K,T.V>\"))},\nj(a){return A.oD(this)},\n$iaa:1}\nA.ki.prototype={\n$1(a){var s=this.a,r=s.i(0,a)\nif(r==null)r=A.t(s).h(\"T.V\").a(r)\nreturn new A.bv(a,r,A.t(s).h(\"bv<T.K,T.V>\"))},\n$S(){return A.t(this.a).h(\"bv<T.K,T.V>(T.K)\")}}\nA.kj.prototype={\n$2(a,b){var s,r=this.a\nif(!r.a)this.b.a+=\", \"\nr.a=!1\nr=this.b\ns=A.u(a)\ns=r.a+=s\nr.a=s+\": \"\ns=A.u(b)\nr.a+=s},\n$S:53}\nA.f_.prototype={\ngl(a){var s=this.a\nreturn s.gl(s)},\ngF(a){var s=this.a\nreturn s.gF(s)},\ngG(a){var s=this.a\ns=s.i(0,J.fy(s.ga_()))\nreturn s==null?this.$ti.y[1].a(s):s},\ngC(a){var s=this.a\ns=s.i(0,J.iS(s.ga_()))\nreturn s==null?this.$ti.y[1].a(s):s},\ngt(a){var s=this.a\nreturn new A.ip(J.M(s.ga_()),s,this.$ti.h(\"ip<1,2>\"))}}\nA.ip.prototype={\nk(){var s=this,r=s.a\nif(r.k()){s.c=s.b.i(0,r.gm())\nreturn!0}s.c=null\nreturn!1},\ngm(){var s=this.c\nreturn s==null?this.$ti.y[1].a(s):s}}\nA.dd.prototype={\ngF(a){return this.a===0},\nbd(a,b,c){return new A.cp(this,b,this.$ti.h(\"@<1>\").H(c).h(\"cp<1,2>\"))},\nj(a){return A.ox(this,\"{\",\"}\")},\nah(a,b){return A.oJ(this,b,this.$ti.c)},\nX(a,b){return A.qf(this,b,this.$ti.c)},\ngG(a){var s,r=A.im(this,this.r,this.$ti.c)\nif(!r.k())throw A.a(A.ak())\ns=r.d\nreturn s==null?r.$ti.c.a(s):s},\ngC(a){var s,r,q=A.im(this,this.r,this.$ti.c)\nif(!q.k())throw A.a(A.ak())\ns=q.$ti.c\ndo{r=q.d\nif(r==null)r=s.a(r)}while(q.k())\nreturn r},\nN(a,b){var s,r,q,p=this\nA.ab(b,\"index\")\ns=A.im(p,p.r,p.$ti.c)\nfor(r=b;s.k();){if(r===0){q=s.d\nreturn q==null?s.$ti.c.a(q):q}--r}throw A.a(A.h4(b,b-r,p,null,\"index\"))},\n$iv:1,\n$if:1}\nA.f8.prototype={}\nA.nE.prototype={\n$0(){var s,r\ntry{s=new TextDecoder(\"utf-8\",{fatal:true})\nreturn s}catch(r){}return null},\n$S:28}\nA.nD.prototype={\n$0(){var s,r\ntry{s=new TextDecoder(\"utf-8\",{fatal:false})\nreturn s}catch(r){}return null},\n$S:28}\nA.fA.prototype={\njO(a){return B.ao.a5(a)}}\nA.iF.prototype={\na5(a){var s,r,q,p=A.b9(0,null,a.length),o=new Uint8Array(p)\nfor(s=~this.a,r=0;r<p;++r){q=a.charCodeAt(r)\nif((q&s)!==0)throw A.a(A.ag(a,\"string\",\"Contains invalid characters.\"))\no[r]=q}return o}}\nA.fB.prototype={}\nA.fF.prototype={\nkh(a0,a1,a2){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a=\"Invalid base64 encoding length \"\na2=A.b9(a1,a2,a0.length)\ns=$.t3()\nfor(r=a1,q=r,p=null,o=-1,n=-1,m=0;r<a2;r=l){l=r+1\nk=a0.charCodeAt(r)\nif(k===37){j=l+2\nif(j<=a2){i=A.o5(a0.charCodeAt(l))\nh=A.o5(a0.charCodeAt(l+1))\ng=i*16+h-(h&256)\nif(g===37)g=-1\nl=j}else g=-1}else g=k\nif(0<=g&&g<=127){f=s[g]\nif(f>=0){g=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\".charCodeAt(f)\nif(g===k)continue\nk=g}else{if(f===-1){if(o<0){e=p==null?null:p.a.length\nif(e==null)e=0\no=e+(r-q)\nn=r}++m\nif(k===61)continue}k=g}if(f!==-2){if(p==null){p=new A.av(\"\")\ne=p}else e=p\ne.a+=B.a.n(a0,q,r)\nd=A.aA(k)\ne.a+=d\nq=l\ncontinue}}throw A.a(A.ai(\"Invalid base64 data\",a0,r))}if(p!=null){e=B.a.n(a0,q,a2)\ne=p.a+=e\nd=e.length\nif(o>=0)A.pA(a0,n,a2,o,m,d)\nelse{c=B.b.aA(d-1,4)+1\nif(c===1)throw A.a(A.ai(a,a0,a2))\nfor(;c<4;){e+=\"=\"\np.a=e;++c}}e=p.a\nreturn B.a.aO(a0,a1,a2,e.charCodeAt(0)==0?e:e)}b=a2-a1\nif(o>=0)A.pA(a0,n,a2,o,m,b)\nelse{c=B.b.aA(b,4)\nif(c===1)throw A.a(A.ai(a,a0,a2))\nif(c>1)a0=B.a.aO(a0,a2,a2,c===2?\"==\":\"=\")}return a0}}\nA.fG.prototype={}\nA.cm.prototype={}\nA.cn.prototype={}\nA.fW.prototype={}\nA.hO.prototype={\ncT(a){return new A.fm(!1).dD(a,0,null,!0)}}\nA.hP.prototype={\na5(a){var s,r,q=A.b9(0,null,a.length)\nif(q===0)return new Uint8Array(0)\ns=new Uint8Array(q*3)\nr=new A.nF(s)\nif(r.ij(a,0,q)!==q)r.e9()\nreturn B.e.a0(s,0,r.b)}}\nA.nF.prototype={\ne9(){var s=this,r=s.c,q=s.b,p=s.b=q+1\nr[q]=239\nq=s.b=p+1\nr[p]=191\ns.b=q+1\nr[q]=189},\njm(a,b){var s,r,q,p,o=this\nif((b&64512)===56320){s=65536+((a&1023)<<10)|b&1023\nr=o.c\nq=o.b\np=o.b=q+1\nr[q]=s>>>18|240\nq=o.b=p+1\nr[p]=s>>>12&63|128\np=o.b=q+1\nr[q]=s>>>6&63|128\no.b=p+1\nr[p]=s&63|128\nreturn!0}else{o.e9()\nreturn!1}},\nij(a,b,c){var s,r,q,p,o,n,m,l=this\nif(b!==c&&(a.charCodeAt(c-1)&64512)===55296)--c\nfor(s=l.c,r=s.length,q=b;q<c;++q){p=a.charCodeAt(q)\nif(p<=127){o=l.b\nif(o>=r)break\nl.b=o+1\ns[o]=p}else{o=p&64512\nif(o===55296){if(l.b+4>r)break\nn=q+1\nif(l.jm(p,a.charCodeAt(n)))q=n}else if(o===56320){if(l.b+3>r)break\nl.e9()}else if(p<=2047){o=l.b\nm=o+1\nif(m>=r)break\nl.b=m\ns[o]=p>>>6|192\nl.b=m+1\ns[m]=p&63|128}else{o=l.b\nif(o+2>=r)break\nm=l.b=o+1\ns[o]=p>>>12|224\no=l.b=m+1\ns[m]=p>>>6&63|128\nl.b=o+1\ns[o]=p&63|128}}}return q}}\nA.fm.prototype={\ndD(a,b,c,d){var s,r,q,p,o,n,m=this,l=A.b9(b,c,J.ae(a))\nif(b===l)return\"\"\nif(a instanceof Uint8Array){s=a\nr=s\nq=0}else{r=A.vz(a,b,l)\nl-=b\nq=b\nb=0}if(d&&l-b>=15){p=m.a\no=A.vy(p,r,b,l)\nif(o!=null){if(!p)return o\nif(o.indexOf(\"\\ufffd\")<0)return o}}o=m.dF(r,b,l,d)\np=m.b\nif((p&1)!==0){n=A.vA(p)\nm.b=0\nthrow A.a(A.ai(n,a,q+m.c))}return o},\ndF(a,b,c,d){var s,r,q=this\nif(c-b>1000){s=B.b.I(b+c,2)\nr=q.dF(a,b,s,!1)\nif((q.b&1)!==0)return r\nreturn r+q.dF(a,s,c,d)}return q.jK(a,b,c,d)},\njK(a,b,c,d){var s,r,q,p,o,n,m,l=this,k=65533,j=l.b,i=l.c,h=new A.av(\"\"),g=b+1,f=a[b]\n$label0$0:for(s=l.a;!0;){for(;!0;g=p){r=\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFFFFFFFFFFFFFFFGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHJEEBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBKCCCCCCCCCCCCDCLONNNMEEEEEEEEEEE\".charCodeAt(f)&31\ni=j<=32?f&61694>>>r:(f&63|i<<6)>>>0\nj=\" \\x000:XECCCCCN:lDb \\x000:XECCCCCNvlDb \\x000:XECCCCCN:lDb AAAAA\\x00\\x00\\x00\\x00\\x00AAAAA00000AAAAA:::::AAAAAGG000AAAAA00KKKAAAAAG::::AAAAA:IIIIAAAAA000\\x800AAAAA\\x00\\x00\\x00\\x00 AAAAA\".charCodeAt(j+r)\nif(j===0){q=A.aA(i)\nh.a+=q\nif(g===c)break $label0$0\nbreak}else if((j&1)!==0){if(s)switch(j){case 69:case 67:q=A.aA(k)\nh.a+=q\nbreak\ncase 65:q=A.aA(k)\nh.a+=q;--g\nbreak\ndefault:q=A.aA(k)\nq=h.a+=q\nh.a=q+A.aA(k)\nbreak}else{l.b=j\nl.c=g-1\nreturn\"\"}j=0}if(g===c)break $label0$0\np=g+1\nf=a[g]}p=g+1\nf=a[g]\nif(f<128){while(!0){if(!(p<c)){o=c\nbreak}n=p+1\nf=a[p]\nif(f>=128){o=n-1\np=n\nbreak}p=n}if(o-g<20)for(m=g;m<o;++m){q=A.aA(a[m])\nh.a+=q}else{q=A.qh(a,g,o)\nh.a+=q}if(o===c)break $label0$0\ng=p}else g=p}if(d&&j>32)if(s){s=A.aA(k)\nh.a+=s}else{l.b=77\nl.c=c\nreturn\"\"}l.b=j\nl.c=i\ns=h.a\nreturn s.charCodeAt(0)==0?s:s}}\nA.a6.prototype={\naB(a){var s,r,q=this,p=q.c\nif(p===0)return q\ns=!q.a\nr=q.b\np=A.aJ(p,r)\nreturn new A.a6(p===0?!1:s,r,p)},\nib(a){var s,r,q,p,o,n,m=this.c\nif(m===0)return $.b7()\ns=m+a\nr=this.b\nq=new Uint16Array(s)\nfor(p=m-1;p>=0;--p)q[p+a]=r[p]\no=this.a\nn=A.aJ(s,q)\nreturn new A.a6(n===0?!1:o,q,n)},\nic(a){var s,r,q,p,o,n,m,l=this,k=l.c\nif(k===0)return $.b7()\ns=k-a\nif(s<=0)return l.a?$.pv():$.b7()\nr=l.b\nq=new Uint16Array(s)\nfor(p=a;p<k;++p)q[p-a]=r[p]\no=l.a\nn=A.aJ(s,q)\nm=new A.a6(n===0?!1:o,q,n)\nif(o)for(p=0;p<a;++p)if(r[p]!==0)return m.dl(0,$.fv())\nreturn m},\nb0(a,b){var s,r,q,p,o,n=this\nif(b<0)throw A.a(A.K(\"shift-amount must be posititve \"+b,null))\ns=n.c\nif(s===0)return n\nr=B.b.I(b,16)\nif(B.b.aA(b,16)===0)return n.ib(r)\nq=s+r+1\np=new Uint16Array(q)\nA.qD(n.b,s,b,p)\ns=n.a\no=A.aJ(q,p)\nreturn new A.a6(o===0?!1:s,p,o)},\nbl(a,b){var s,r,q,p,o,n,m,l,k,j=this\nif(b<0)throw A.a(A.K(\"shift-amount must be posititve \"+b,null))\ns=j.c\nif(s===0)return j\nr=B.b.I(b,16)\nq=B.b.aA(b,16)\nif(q===0)return j.ic(r)\np=s-r\nif(p<=0)return j.a?$.pv():$.b7()\no=j.b\nn=new Uint16Array(p)\nA.uZ(o,s,b,n)\ns=j.a\nm=A.aJ(p,n)\nl=new A.a6(m===0?!1:s,n,m)\nif(s){if((o[r]&B.b.b0(1,q)-1)>>>0!==0)return l.dl(0,$.fv())\nfor(k=0;k<r;++k)if(o[k]!==0)return l.dl(0,$.fv())}return l},\nag(a,b){var s,r=this.a\nif(r===b.a){s=A.lZ(this.b,this.c,b.b,b.c)\nreturn r?0-s:s}return r?-1:1},\ndr(a,b){var s,r,q,p=this,o=p.c,n=a.c\nif(o<n)return a.dr(p,b)\nif(o===0)return $.b7()\nif(n===0)return p.a===b?p:p.aB(0)\ns=o+1\nr=new Uint16Array(s)\nA.uV(p.b,o,a.b,n,r)\nq=A.aJ(s,r)\nreturn new A.a6(q===0?!1:b,r,q)},\ncs(a,b){var s,r,q,p=this,o=p.c\nif(o===0)return $.b7()\ns=a.c\nif(s===0)return p.a===b?p:p.aB(0)\nr=new Uint16Array(o)\nA.i4(p.b,o,a.b,s,r)\nq=A.aJ(o,r)\nreturn new A.a6(q===0?!1:b,r,q)},\ndh(a,b){var s,r,q=this,p=q.c\nif(p===0)return b\ns=b.c\nif(s===0)return q\nr=q.a\nif(r===b.a)return q.dr(b,r)\nif(A.lZ(q.b,p,b.b,s)>=0)return q.cs(b,r)\nreturn b.cs(q,!r)},\ndl(a,b){var s,r,q=this,p=q.c\nif(p===0)return b.aB(0)\ns=b.c\nif(s===0)return q\nr=q.a\nif(r!==b.a)return q.dr(b,r)\nif(A.lZ(q.b,p,b.b,s)>=0)return q.cs(b,r)\nreturn b.cs(q,!r)},\nbI(a,b){var s,r,q,p,o,n,m,l=this.c,k=b.c\nif(l===0||k===0)return $.b7()\ns=l+k\nr=this.b\nq=b.b\np=new Uint16Array(s)\nfor(o=0;o<k;){A.qE(q[o],r,0,p,o,l);++o}n=this.a!==b.a\nm=A.aJ(s,p)\nreturn new A.a6(m===0?!1:n,p,m)},\nia(a){var s,r,q,p\nif(this.c<a.c)return $.b7()\nthis.fb(a)\ns=$.oQ.af()-$.eK.af()\nr=A.oS($.oP.af(),$.eK.af(),$.oQ.af(),s)\nq=A.aJ(s,r)\np=new A.a6(!1,r,q)\nreturn this.a!==a.a&&q>0?p.aB(0):p},\niT(a){var s,r,q,p=this\nif(p.c<a.c)return p\np.fb(a)\ns=A.oS($.oP.af(),0,$.eK.af(),$.eK.af())\nr=A.aJ($.eK.af(),s)\nq=new A.a6(!1,s,r)\nif($.oR.af()>0)q=q.bl(0,$.oR.af())\nreturn p.a&&q.c>0?q.aB(0):q},\nfb(a){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d=this,c=d.c\nif(c===$.qA&&a.c===$.qC&&d.b===$.qz&&a.b===$.qB)return\ns=a.b\nr=a.c\nq=16-B.b.gfV(s[r-1])\nif(q>0){p=new Uint16Array(r+5)\no=A.qy(s,r,q,p)\nn=new Uint16Array(c+5)\nm=A.qy(d.b,c,q,n)}else{n=A.oS(d.b,0,c,c+2)\no=r\np=s\nm=c}l=p[o-1]\nk=m-o\nj=new Uint16Array(m)\ni=A.oT(p,o,k,j)\nh=m+1\nif(A.lZ(n,m,j,i)>=0){n[m]=1\nA.i4(n,h,j,i,n)}else n[m]=0\ng=new Uint16Array(o+2)\ng[o]=1\nA.i4(g,o+1,p,o,g)\nf=m-1\nfor(;k>0;){e=A.uW(l,n,f);--k\nA.qE(e,g,0,n,k,o)\nif(n[f]<e){i=A.oT(g,o,k,j)\nA.i4(n,h,j,i,n)\nfor(;--e,n[f]<e;)A.i4(n,h,j,i,n)}--f}$.qz=d.b\n$.qA=c\n$.qB=s\n$.qC=r\n$.oP.b=n\n$.oQ.b=h\n$.eK.b=o\n$.oR.b=q},\ngB(a){var s,r,q,p=new A.m_(),o=this.c\nif(o===0)return 6707\ns=this.a?83585:429689\nfor(r=this.b,q=0;q<o;++q)s=p.$2(s,r[q])\nreturn new A.m0().$1(s)},\nO(a,b){if(b==null)return!1\nreturn b instanceof A.a6&&this.ag(0,b)===0},\nj(a){var s,r,q,p,o,n=this,m=n.c\nif(m===0)return\"0\"\nif(m===1){if(n.a)return B.b.j(-n.b[0])\nreturn B.b.j(n.b[0])}s=A.d([],t.s)\nm=n.a\nr=m?n.aB(0):n\nfor(;r.c>1;){q=$.pu()\nif(q.c===0)A.y(B.as)\np=r.iT(q).j(0)\ns.push(p)\no=p.length\nif(o===1)s.push(\"000\")\nif(o===2)s.push(\"00\")\nif(o===3)s.push(\"0\")\nr=r.ia(q)}s.push(B.b.j(r.b[0]))\nif(m)s.push(\"-\")\nreturn new A.ew(s,t.bJ).c5(0)}}\nA.m_.prototype={\n$2(a,b){a=a+b&536870911\na=a+((a&524287)<<10)&536870911\nreturn a^a>>>6},\n$S:4}\nA.m0.prototype={\n$1(a){a=a+((a&67108863)<<3)&536870911\na^=a>>>11\nreturn a+((a&16383)<<15)&536870911},\n$S:12}\nA.ie.prototype={\nh_(a){var s=this.a\nif(s!=null)s.unregister(a)}}\nA.fN.prototype={\nO(a,b){if(b==null)return!1\nreturn b instanceof A.fN&&this.a===b.a&&this.b===b.b&&this.c===b.c},\ngB(a){return A.es(this.a,this.b,B.f,B.f)},\nag(a,b){var s=B.b.ag(this.a,b.a)\nif(s!==0)return s\nreturn B.b.ag(this.b,b.b)},\nj(a){var s=this,r=A.tV(A.ux(s)),q=A.fO(A.uv(s)),p=A.fO(A.ur(s)),o=A.fO(A.us(s)),n=A.fO(A.uu(s)),m=A.fO(A.uw(s)),l=A.pI(A.ut(s)),k=s.b,j=k===0?\"\":A.pI(k)\nk=r+\"-\"+q\nif(s.c)return k+\"-\"+p+\" \"+o+\":\"+n+\":\"+m+\".\"+l+j+\"Z\"\nelse return k+\"-\"+p+\" \"+o+\":\"+n+\":\"+m+\".\"+l+j}}\nA.bp.prototype={\nO(a,b){if(b==null)return!1\nreturn b instanceof A.bp&&this.a===b.a},\ngB(a){return B.b.gB(this.a)},\nag(a,b){return B.b.ag(this.a,b.a)},\nj(a){var s,r,q,p,o,n=this.a,m=B.b.I(n,36e8),l=n%36e8\nif(n<0){m=0-m\nn=0-l\ns=\"-\"}else{n=l\ns=\"\"}r=B.b.I(n,6e7)\nn%=6e7\nq=r<10?\"0\":\"\"\np=B.b.I(n,1e6)\no=p<10?\"0\":\"\"\nreturn s+m+\":\"+q+r+\":\"+o+p+\".\"+B.a.kl(B.b.j(n%1e6),6,\"0\")}}\nA.md.prototype={\nj(a){return this.ae()}}\nA.O.prototype={\ngbJ(){return A.uq(this)}}\nA.fC.prototype={\nj(a){var s=this.a\nif(s!=null)return\"Assertion failed: \"+A.fX(s)\nreturn\"Assertion failed\"}}\nA.bD.prototype={}\nA.aV.prototype={\ngdJ(){return\"Invalid argument\"+(!this.a?\"(s)\":\"\")},\ngdI(){return\"\"},\nj(a){var s=this,r=s.c,q=r==null?\"\":\" (\"+r+\")\",p=s.d,o=p==null?\"\":\": \"+A.u(p),n=s.gdJ()+q+o\nif(!s.a)return n\nreturn n+s.gdI()+\": \"+A.fX(s.gex())},\ngex(){return this.b}}\nA.d7.prototype={\ngex(){return this.b},\ngdJ(){return\"RangeError\"},\ngdI(){var s,r=this.e,q=this.f\nif(r==null)s=q!=null?\": Not less than or equal to \"+A.u(q):\"\"\nelse if(q==null)s=\": Not greater than or equal to \"+A.u(r)\nelse if(q>r)s=\": Not in inclusive range \"+A.u(r)+\"..\"+A.u(q)\nelse s=q<r?\": Valid value range is empty\":\": Only valid value is \"+A.u(r)\nreturn s}}\nA.h3.prototype={\ngex(){return this.b},\ngdJ(){return\"RangeError\"},\ngdI(){if(this.b<0)return\": index must not be negative\"\nvar s=this.f\nif(s===0)return\": no indices are valid\"\nreturn\": index should be less than \"+s},\ngl(a){return this.f}}\nA.hL.prototype={\nj(a){return\"Unsupported operation: \"+this.a}}\nA.hH.prototype={\nj(a){return\"UnimplementedError: \"+this.a}}\nA.b2.prototype={\nj(a){return\"Bad state: \"+this.a}}\nA.fK.prototype={\nj(a){var s=this.a\nif(s==null)return\"Concurrent modification during iteration.\"\nreturn\"Concurrent modification during iteration: \"+A.fX(s)+\".\"}}\nA.hq.prototype={\nj(a){return\"Out of Memory\"},\ngbJ(){return null},\n$iO:1}\nA.eA.prototype={\nj(a){return\"Stack Overflow\"},\ngbJ(){return null},\n$iO:1}\nA.id.prototype={\nj(a){return\"Exception: \"+this.a},\n$ia5:1}\nA.bs.prototype={\nj(a){var s,r,q,p,o,n,m,l,k,j,i,h=this.a,g=\"\"!==h?\"FormatException: \"+h:\"FormatException\",f=this.c,e=this.b\nif(typeof e==\"string\"){if(f!=null)s=f<0||f>e.length\nelse s=!1\nif(s)f=null\nif(f==null){if(e.length>78)e=B.a.n(e,0,75)+\"...\"\nreturn g+\"\\n\"+e}for(r=1,q=0,p=!1,o=0;o<f;++o){n=e.charCodeAt(o)\nif(n===10){if(q!==o||!p)++r\nq=o+1\np=!1}else if(n===13){++r\nq=o+1\np=!0}}g=r>1?g+(\" (at line \"+r+\", character \"+(f-q+1)+\")\\n\"):g+(\" (at character \"+(f+1)+\")\\n\")\nm=e.length\nfor(o=f;o<m;++o){n=e.charCodeAt(o)\nif(n===10||n===13){m=o\nbreak}}l=\"\"\nif(m-q>78){k=\"...\"\nif(f-q<75){j=q+75\ni=q}else{if(m-f<75){i=m-75\nj=m\nk=\"\"}else{i=f-36\nj=f+36}l=\"...\"}}else{j=m\ni=q\nk=\"\"}return g+l+B.a.n(e,i,j)+k+\"\\n\"+B.a.bI(\" \",f-i+l.length)+\"^\\n\"}else return f!=null?g+(\" (at offset \"+A.u(f)+\")\"):g},\n$ia5:1}\nA.h6.prototype={\ngbJ(){return null},\nj(a){return\"IntegerDivisionByZeroException\"},\n$iO:1,\n$ia5:1}\nA.f.prototype={\nb8(a,b){return A.e4(this,A.t(this).h(\"f.E\"),b)},\nbd(a,b,c){return A.en(this,b,A.t(this).h(\"f.E\"),c)},\naz(a,b){return A.ay(this,b,A.t(this).h(\"f.E\"))},\ncj(a){return this.az(0,!0)},\ngl(a){var s,r=this.gt(this)\nfor(s=0;r.k();)++s\nreturn s},\ngF(a){return!this.gt(this).k()},\nah(a,b){return A.oJ(this,b,A.t(this).h(\"f.E\"))},\nX(a,b){return A.qf(this,b,A.t(this).h(\"f.E\"))},\nhA(a,b){return new A.ex(this,b,A.t(this).h(\"ex<f.E>\"))},\ngG(a){var s=this.gt(this)\nif(!s.k())throw A.a(A.ak())\nreturn s.gm()},\ngC(a){var s,r=this.gt(this)\nif(!r.k())throw A.a(A.ak())\ndo s=r.gm()\nwhile(r.k())\nreturn s},\nN(a,b){var s,r\nA.ab(b,\"index\")\ns=this.gt(this)\nfor(r=b;s.k();){if(r===0)return s.gm();--r}throw A.a(A.h4(b,b-r,this,null,\"index\"))},\nj(a){return A.ub(this,\"(\",\")\")}}\nA.bv.prototype={\nj(a){return\"MapEntry(\"+A.u(this.a)+\": \"+A.u(this.b)+\")\"}}\nA.F.prototype={\ngB(a){return A.e.prototype.gB.call(this,0)},\nj(a){return\"null\"}}\nA.e.prototype={$ie:1,\nO(a,b){return this===b},\ngB(a){return A.ev(this)},\nj(a){return\"Instance of '\"+A.kp(this)+\"'\"},\ngV(a){return A.x5(this)},\ntoString(){return this.j(this)}}\nA.dI.prototype={\nj(a){return this.a},\n$ia0:1}\nA.av.prototype={\ngl(a){return this.a.length},\nj(a){var s=this.a\nreturn s.charCodeAt(0)==0?s:s}}\nA.lh.prototype={\n$2(a,b){throw A.a(A.ai(\"Illegal IPv4 address, \"+a,this.a,b))},\n$S:75}\nA.li.prototype={\n$2(a,b){throw A.a(A.ai(\"Illegal IPv6 address, \"+a,this.a,b))},\n$S:76}\nA.lj.prototype={\n$2(a,b){var s\nif(b-a>4)this.a.$2(\"an IPv6 part can only contain a maximum of 4 hex digits\",a)\ns=A.aN(B.a.n(this.b,a,b),16)\nif(s<0||s>65535)this.a.$2(\"each part must be in the range of `0x0..0xFFFF`\",a)\nreturn s},\n$S:4}\nA.fj.prototype={\ngfM(){var s,r,q,p,o=this,n=o.w\nif(n===$){s=o.a\nr=s.length!==0?\"\"+s+\":\":\"\"\nq=o.c\np=q==null\nif(!p||s===\"file\"){s=r+\"//\"\nr=o.b\nif(r.length!==0)s=s+r+\"@\"\nif(!p)s+=q\nr=o.d\nif(r!=null)s=s+\":\"+A.u(r)}else s=r\ns+=o.e\nr=o.f\nif(r!=null)s=s+\"?\"+r\nr=o.r\nif(r!=null)s=s+\"#\"+r\nn!==$&&A.oj()\nn=o.w=s.charCodeAt(0)==0?s:s}return n},\ngkm(){var s,r,q=this,p=q.x\nif(p===$){s=q.e\nif(s.length!==0&&s.charCodeAt(0)===47)s=B.a.K(s,1)\nr=s.length===0?B.r:A.aG(new A.D(A.d(s.split(\"/\"),t.s),A.wU(),t.do),t.N)\nq.x!==$&&A.oj()\np=q.x=r}return p},\ngB(a){var s,r=this,q=r.y\nif(q===$){s=B.a.gB(r.gfM())\nr.y!==$&&A.oj()\nr.y=s\nq=s}return q},\ngeO(){return this.b},\ngbc(){var s=this.c\nif(s==null)return\"\"\nif(B.a.u(s,\"[\"))return B.a.n(s,1,s.length-1)\nreturn s},\ngcb(){var s=this.d\nreturn s==null?A.qV(this.a):s},\ngcd(){var s=this.f\nreturn s==null?\"\":s},\ngcW(){var s=this.r\nreturn s==null?\"\":s},\nkc(a){var s=this.a\nif(a.length!==s.length)return!1\nreturn A.vM(a,s,0)>=0},\nhk(a){var s,r,q,p,o,n,m,l=this\na=A.nC(a,0,a.length)\ns=a===\"file\"\nr=l.b\nq=l.d\nif(a!==l.a)q=A.nB(q,a)\np=l.c\nif(!(p!=null))p=r.length!==0||q!=null||s?\"\":null\no=l.e\nif(!s)n=p!=null&&o.length!==0\nelse n=!0\nif(n&&!B.a.u(o,\"/\"))o=\"/\"+o\nm=o\nreturn A.fk(a,r,p,q,m,l.f,l.r)},\ngh7(){if(this.a!==\"\"){var s=this.r\ns=(s==null?\"\":s)===\"\"}else s=!1\nreturn s},\nfn(a,b){var s,r,q,p,o,n,m\nfor(s=0,r=0;B.a.E(b,\"../\",r);){r+=3;++s}q=B.a.d0(a,\"/\")\nwhile(!0){if(!(q>0&&s>0))break\np=B.a.h9(a,\"/\",q-1)\nif(p<0)break\no=q-p\nn=o!==2\nm=!1\nif(!n||o===3)if(a.charCodeAt(p+1)===46)n=!n||a.charCodeAt(p+2)===46\nelse n=m\nelse n=m\nif(n)break;--s\nq=p}return B.a.aO(a,q+1,null,B.a.K(b,r-3*s))},\nhm(a){return this.ce(A.bm(a))},\nce(a){var s,r,q,p,o,n,m,l,k,j,i,h=this\nif(a.gY().length!==0)return a\nelse{s=h.a\nif(a.geq()){r=a.hk(s)\nreturn r}else{q=h.b\np=h.c\no=h.d\nn=h.e\nif(a.gh5())m=a.gcX()?a.gcd():h.f\nelse{l=A.vw(h,n)\nif(l>0){k=B.a.n(n,0,l)\nn=a.gep()?k+A.cJ(a.gac()):k+A.cJ(h.fn(B.a.K(n,k.length),a.gac()))}else if(a.gep())n=A.cJ(a.gac())\nelse if(n.length===0)if(p==null)n=s.length===0?a.gac():A.cJ(a.gac())\nelse n=A.cJ(\"/\"+a.gac())\nelse{j=h.fn(n,a.gac())\nr=s.length===0\nif(!r||p!=null||B.a.u(n,\"/\"))n=A.cJ(j)\nelse n=A.p3(j,!r||p!=null)}m=a.gcX()?a.gcd():null}}}i=a.ger()?a.gcW():null\nreturn A.fk(s,q,p,o,n,m,i)},\ngeq(){return this.c!=null},\ngcX(){return this.f!=null},\nger(){return this.r!=null},\ngh5(){return this.e.length===0},\ngep(){return B.a.u(this.e,\"/\")},\neL(){var s,r=this,q=r.a\nif(q!==\"\"&&q!==\"file\")throw A.a(A.H(\"Cannot extract a file path from a \"+q+\" URI\"))\nq=r.f\nif((q==null?\"\":q)!==\"\")throw A.a(A.H(u.y))\nq=r.r\nif((q==null?\"\":q)!==\"\")throw A.a(A.H(u.l))\nif(r.c!=null&&r.gbc()!==\"\")A.y(A.H(u.j))\ns=r.gkm()\nA.vo(s,!1)\nq=A.oH(B.a.u(r.e,\"/\")?\"\"+\"/\":\"\",s,\"/\")\nq=q.charCodeAt(0)==0?q:q\nreturn q},\nj(a){return this.gfM()},\nO(a,b){var s,r,q,p=this\nif(b==null)return!1\nif(p===b)return!0\ns=!1\nif(t.dD.b(b))if(p.a===b.gY())if(p.c!=null===b.geq())if(p.b===b.geO())if(p.gbc()===b.gbc())if(p.gcb()===b.gcb())if(p.e===b.gac()){r=p.f\nq=r==null\nif(!q===b.gcX()){if(q)r=\"\"\nif(r===b.gcd()){r=p.r\nq=r==null\nif(!q===b.ger()){s=q?\"\":r\ns=s===b.gcW()}}}}return s},\n$ihM:1,\ngY(){return this.a},\ngac(){return this.e}}\nA.nA.prototype={\n$1(a){return A.vx(B.aN,a,B.j,!1)},\n$S:8}\nA.hN.prototype={\ngeN(){var s,r,q,p,o=this,n=null,m=o.c\nif(m==null){m=o.a\ns=o.b[0]+1\nr=B.a.aW(m,\"?\",s)\nq=m.length\nif(r>=0){p=A.fl(m,r+1,q,B.p,!1,!1)\nq=r}else p=n\nm=o.c=new A.i9(\"data\",\"\",n,n,A.fl(m,s,q,B.a5,!1,!1),p,n)}return m},\nj(a){var s=this.a\nreturn this.b[0]===-1?\"data:\"+s:s}}\nA.nN.prototype={\n$2(a,b){var s=this.a[a]\nB.e.en(s,0,96,b)\nreturn s},\n$S:78}\nA.nO.prototype={\n$3(a,b,c){var s,r\nfor(s=b.length,r=0;r<s;++r)a[b.charCodeAt(r)^96]=c},\n$S:23}\nA.nP.prototype={\n$3(a,b,c){var s,r\nfor(s=b.charCodeAt(0),r=b.charCodeAt(1);s<=r;++s)a[(s^96)>>>0]=c},\n$S:23}\nA.b4.prototype={\ngeq(){return this.c>0},\nges(){return this.c>0&&this.d+1<this.e},\ngcX(){return this.f<this.r},\nger(){return this.r<this.a.length},\ngep(){return B.a.E(this.a,\"/\",this.e)},\ngh5(){return this.e===this.f},\ngh7(){return this.b>0&&this.r>=this.a.length},\ngY(){var s=this.w\nreturn s==null?this.w=this.i2():s},\ni2(){var s,r=this,q=r.b\nif(q<=0)return\"\"\ns=q===4\nif(s&&B.a.u(r.a,\"http\"))return\"http\"\nif(q===5&&B.a.u(r.a,\"https\"))return\"https\"\nif(s&&B.a.u(r.a,\"file\"))return\"file\"\nif(q===7&&B.a.u(r.a,\"package\"))return\"package\"\nreturn B.a.n(r.a,0,q)},\ngeO(){var s=this.c,r=this.b+3\nreturn s>r?B.a.n(this.a,r,s-1):\"\"},\ngbc(){var s=this.c\nreturn s>0?B.a.n(this.a,s,this.d):\"\"},\ngcb(){var s,r=this\nif(r.ges())return A.aN(B.a.n(r.a,r.d+1,r.e),null)\ns=r.b\nif(s===4&&B.a.u(r.a,\"http\"))return 80\nif(s===5&&B.a.u(r.a,\"https\"))return 443\nreturn 0},\ngac(){return B.a.n(this.a,this.e,this.f)},\ngcd(){var s=this.f,r=this.r\nreturn s<r?B.a.n(this.a,s+1,r):\"\"},\ngcW(){var s=this.r,r=this.a\nreturn s<r.length?B.a.K(r,s+1):\"\"},\nfk(a){var s=this.d+1\nreturn s+a.length===this.e&&B.a.E(this.a,a,s)},\nkt(){var s=this,r=s.r,q=s.a\nif(r>=q.length)return s\nreturn new A.b4(B.a.n(q,0,r),s.b,s.c,s.d,s.e,s.f,r,s.w)},\nhk(a){var s,r,q,p,o,n,m,l,k,j,i,h=this,g=null\na=A.nC(a,0,a.length)\ns=!(h.b===a.length&&B.a.u(h.a,a))\nr=a===\"file\"\nq=h.c\np=q>0?B.a.n(h.a,h.b+3,q):\"\"\no=h.ges()?h.gcb():g\nif(s)o=A.nB(o,a)\nq=h.c\nif(q>0)n=B.a.n(h.a,q,h.d)\nelse n=p.length!==0||o!=null||r?\"\":g\nq=h.a\nm=h.f\nl=B.a.n(q,h.e,m)\nif(!r)k=n!=null&&l.length!==0\nelse k=!0\nif(k&&!B.a.u(l,\"/\"))l=\"/\"+l\nk=h.r\nj=m<k?B.a.n(q,m+1,k):g\nm=h.r\ni=m<q.length?B.a.K(q,m+1):g\nreturn A.fk(a,p,n,o,l,j,i)},\nhm(a){return this.ce(A.bm(a))},\nce(a){if(a instanceof A.b4)return this.jb(this,a)\nreturn this.fO().ce(a)},\njb(a,b){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c=b.b\nif(c>0)return b\ns=b.c\nif(s>0){r=a.b\nif(r<=0)return b\nq=r===4\nif(q&&B.a.u(a.a,\"file\"))p=b.e!==b.f\nelse if(q&&B.a.u(a.a,\"http\"))p=!b.fk(\"80\")\nelse p=!(r===5&&B.a.u(a.a,\"https\"))||!b.fk(\"443\")\nif(p){o=r+1\nreturn new A.b4(B.a.n(a.a,0,o)+B.a.K(b.a,c+1),r,s+o,b.d+o,b.e+o,b.f+o,b.r+o,a.w)}else return this.fO().ce(b)}n=b.e\nc=b.f\nif(n===c){s=b.r\nif(c<s){r=a.f\no=r-c\nreturn new A.b4(B.a.n(a.a,0,r)+B.a.K(b.a,c),a.b,a.c,a.d,a.e,c+o,s+o,a.w)}c=b.a\nif(s<c.length){r=a.r\nreturn new A.b4(B.a.n(a.a,0,r)+B.a.K(c,s),a.b,a.c,a.d,a.e,a.f,s+(r-s),a.w)}return a.kt()}s=b.a\nif(B.a.E(s,\"/\",n)){m=a.e\nl=A.qN(this)\nk=l>0?l:m\no=k-n\nreturn new A.b4(B.a.n(a.a,0,k)+B.a.K(s,n),a.b,a.c,a.d,m,c+o,b.r+o,a.w)}j=a.e\ni=a.f\nif(j===i&&a.c>0){for(;B.a.E(s,\"../\",n);)n+=3\no=j-n+1\nreturn new A.b4(B.a.n(a.a,0,j)+\"/\"+B.a.K(s,n),a.b,a.c,a.d,j,c+o,b.r+o,a.w)}h=a.a\nl=A.qN(this)\nif(l>=0)g=l\nelse for(g=j;B.a.E(h,\"../\",g);)g+=3\nf=0\nwhile(!0){e=n+3\nif(!(e<=c&&B.a.E(s,\"../\",n)))break;++f\nn=e}for(d=\"\";i>g;){--i\nif(h.charCodeAt(i)===47){if(f===0){d=\"/\"\nbreak}--f\nd=\"/\"}}if(i===g&&a.b<=0&&!B.a.E(h,\"/\",j)){n-=f*3\nd=\"\"}o=i-n+d.length\nreturn new A.b4(B.a.n(h,0,i)+d+B.a.K(s,n),a.b,a.c,a.d,j,c+o,b.r+o,a.w)},\neL(){var s,r=this,q=r.b\nif(q>=0){s=!(q===4&&B.a.u(r.a,\"file\"))\nq=s}else q=!1\nif(q)throw A.a(A.H(\"Cannot extract a file path from a \"+r.gY()+\" URI\"))\nq=r.f\ns=r.a\nif(q<s.length){if(q<r.r)throw A.a(A.H(u.y))\nthrow A.a(A.H(u.l))}if(r.c<r.d)A.y(A.H(u.j))\nq=B.a.n(s,r.e,q)\nreturn q},\ngB(a){var s=this.x\nreturn s==null?this.x=B.a.gB(this.a):s},\nO(a,b){if(b==null)return!1\nif(this===b)return!0\nreturn t.dD.b(b)&&this.a===b.j(0)},\nfO(){var s=this,r=null,q=s.gY(),p=s.geO(),o=s.c>0?s.gbc():r,n=s.ges()?s.gcb():r,m=s.a,l=s.f,k=B.a.n(m,s.e,l),j=s.r\nl=l<j?s.gcd():r\nreturn A.fk(q,p,o,n,k,l,j<m.length?s.gcW():r)},\nj(a){return this.a},\n$ihM:1}\nA.i9.prototype={}\nA.fZ.prototype={\ni(a,b){A.u_(b)\nreturn this.a.get(b)},\nj(a){return\"Expando:null\"}}\nA.oa.prototype={\n$1(a){var s,r,q,p\nif(A.rj(a))return a\ns=this.a\nif(s.a4(a))return s.i(0,a)\nif(t.cv.b(a)){r={}\ns.q(0,a,r)\nfor(s=J.M(a.ga_());s.k();){q=s.gm()\nr[q]=this.$1(a.i(0,q))}return r}else if(t.dP.b(a)){p=[]\ns.q(0,a,p)\nB.c.aJ(p,J.cQ(a,this,t.z))\nreturn p}else return a},\n$S:13}\nA.oe.prototype={\n$1(a){return this.a.L(a)},\n$S:16}\nA.of.prototype={\n$1(a){if(a==null)return this.a.aK(new A.ho(a===undefined))\nreturn this.a.aK(a)},\n$S:16}\nA.o1.prototype={\n$1(a){var s,r,q,p,o,n,m,l,k,j,i,h\nif(A.ri(a))return a\ns=this.a\na.toString\nif(s.a4(a))return s.i(0,a)\nif(a instanceof Date){r=a.getTime()\nif(r<-864e13||r>864e13)A.y(A.a4(r,-864e13,864e13,\"millisecondsSinceEpoch\",null))\nA.aD(!0,\"isUtc\",t.y)\nreturn new A.fN(r,0,!0)}if(a instanceof RegExp)throw A.a(A.K(\"structured clone of RegExp\",null))\nif(typeof Promise!=\"undefined\"&&a instanceof Promise)return A.a_(a,t.X)\nq=Object.getPrototypeOf(a)\nif(q===Object.prototype||q===null){p=t.X\no=A.a3(p,p)\ns.q(0,a,o)\nn=Object.keys(a)\nm=[]\nfor(s=J.aM(n),p=s.gt(n);p.k();)m.push(A.ry(p.gm()))\nfor(l=0;l<s.gl(n);++l){k=s.i(n,l)\nj=m[l]\nif(k!=null)o.q(0,j,this.$1(a[k]))}return o}if(a instanceof Array){i=a\no=[]\ns.q(0,a,o)\nh=a.length\nfor(s=J.V(i),l=0;l<h;++l)o.push(this.$1(s.i(i,l)))\nreturn o}return a},\n$S:13}\nA.ho.prototype={\nj(a){return\"Promise was rejected with a value of `\"+(this.a?\"undefined\":\"null\")+\"`.\"},\n$ia5:1}\nA.nc.prototype={\nhQ(){var s=self.crypto\nif(s!=null)if(s.getRandomValues!=null)return\nthrow A.a(A.H(\"No source of cryptographically secure random numbers available.\"))},\nhc(a){var s,r,q,p,o,n,m,l,k,j=null\nif(a<=0||a>4294967296)throw A.a(new A.d7(j,j,!1,j,j,\"max must be in range 0 < max \\u2264 2^32, was \"+a))\nif(a>255)if(a>65535)s=a>16777215?4:3\nelse s=2\nelse s=1\nr=this.a\nr.setUint32(0,0,!1)\nq=4-s\np=A.h(Math.pow(256,s))\nfor(o=a-1,n=(a&o)===0;!0;){m=r.buffer\nm=new Uint8Array(m,q,s)\ncrypto.getRandomValues(m)\nl=r.getUint32(0,!1)\nif(n)return(l&o)>>>0\nk=l%a\nif(l-k+a<p)return k}}}\nA.cU.prototype={\nv(a,b){this.a.v(0,b)},\na3(a,b){this.a.a3(a,b)},\np(){return this.a.p()},\n$ia9:1}\nA.fP.prototype={}\nA.hf.prototype={\nem(a,b){var s,r,q,p\nif(a===b)return!0\ns=J.V(a)\nr=s.gl(a)\nq=J.V(b)\nif(r!==q.gl(b))return!1\nfor(p=0;p<r;++p)if(!J.X(s.i(a,p),q.i(b,p)))return!1\nreturn!0},\nh6(a){var s,r,q\nfor(s=J.V(a),r=0,q=0;q<s.gl(a);++q){r=r+J.aw(s.i(a,q))&2147483647\nr=r+(r<<10>>>0)&2147483647\nr^=r>>>6}r=r+(r<<3>>>0)&2147483647\nr^=r>>>11\nreturn r+(r<<15>>>0)&2147483647}}\nA.hn.prototype={}\nA.hK.prototype={}\nA.ea.prototype={\nhK(a,b,c){var s=this.a.a\ns===$&&A.G()\ns.eB(this.gip(),new A.jA(this))},\nhb(){return this.d++},\np(){var s=0,r=A.o(t.H),q,p=this,o\nvar $async$p=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:if(p.r||(p.w.a.a&30)!==0){s=1\nbreak}p.r=!0\no=p.a.b\no===$&&A.G()\no.p()\ns=3\nreturn A.c(p.w.a,$async$p)\ncase 3:case 1:return A.m(q,r)}})\nreturn A.n($async$p,r)},\niq(a){var s,r=this\nif(r.c){a.toString\na=B.a_.ej(a)}if(a instanceof A.ba){s=r.e.A(0,a.a)\nif(s!=null)s.a.L(a.b)}else if(a instanceof A.bq){s=r.e.A(0,a.a)\nif(s!=null)s.fX(new A.fT(a.b),a.c)}else if(a instanceof A.am)r.f.v(0,a)\nelse if(a instanceof A.bo){s=r.e.A(0,a.a)\nif(s!=null)s.fW(B.Z)}},\nbv(a){var s,r,q=this\nif(q.r||(q.w.a.a&30)!==0)throw A.a(A.B(\"Tried to send \"+a.j(0)+\" over isolate channel, but the connection was closed!\"))\ns=q.a.b\ns===$&&A.G()\nr=q.c?B.a_.dk(a):a\ns.a.v(0,r)},\nku(a,b,c){var s,r=this\nif(r.r||(r.w.a.a&30)!==0)return\ns=a.a\nif(b instanceof A.e3)r.bv(new A.bo(s))\nelse r.bv(new A.bq(s,b,c))},\nhx(a){var s=this.f\nnew A.an(s,A.t(s).h(\"an<1>\")).kf(new A.jB(this,a))}}\nA.jA.prototype={\n$0(){var s,r,q,p,o\nfor(s=this.a,r=s.e,q=r.gaP(),p=A.t(q),q=new A.b0(J.M(q.a),q.b,p.h(\"b0<1,2>\")),p=p.y[1];q.k();){o=q.a;(o==null?p.a(o):o).fW(B.ar)}r.c1(0)\ns.w.aV()},\n$S:0}\nA.jB.prototype={\n$1(a){return this.hs(a)},\nhs(a){var s=0,r=A.o(t.H),q,p=2,o,n=this,m,l,k,j,i,h\nvar $async$$1=A.p(function(b,c){if(b===1){o=c\ns=p}while(true)switch(s){case 0:i=null\np=4\nk=n.b.$1(a)\ns=7\nreturn A.c(t.cG.b(k)?k:A.eX(k,t.O),$async$$1)\ncase 7:i=c\np=2\ns=6\nbreak\ncase 4:p=3\nh=o\nm=A.E(h)\nl=A.R(h)\nk=n.a.ku(a,m,l)\nq=k\ns=1\nbreak\ns=6\nbreak\ncase 3:s=2\nbreak\ncase 6:k=n.a\nif(!(k.r||(k.w.a.a&30)!==0))k.bv(new A.ba(a.a,i))\ncase 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$$1,r)},\n$S:86}\nA.ir.prototype={\nfX(a,b){var s\nif(b==null)s=this.b\nelse{s=A.d([],t.J)\nif(b instanceof A.be)B.c.aJ(s,b.a)\nelse s.push(A.qm(b))\ns.push(A.qm(this.b))\ns=new A.be(A.aG(s,t.a))}this.a.bx(a,s)},\nfW(a){return this.fX(a,null)}}\nA.fL.prototype={\nj(a){return\"Channel was closed before receiving a response\"},\n$ia5:1}\nA.fT.prototype={\nj(a){return J.aU(this.a)},\n$ia5:1}\nA.fS.prototype={\ndk(a){var s,r\nif(a instanceof A.am)return[0,a.a,this.h0(a.b)]\nelse if(a instanceof A.bq){s=J.aU(a.b)\nr=a.c\nr=r==null?null:r.j(0)\nreturn[2,a.a,s,r]}else if(a instanceof A.ba)return[1,a.a,this.h0(a.b)]\nelse if(a instanceof A.bo)return A.d([3,a.a],t.t)\nelse return null},\nej(a){var s,r,q,p\nif(!t.j.b(a))throw A.a(B.aE)\ns=J.V(a)\nr=A.h(s.i(a,0))\nq=A.h(s.i(a,1))\nswitch(r){case 0:return new A.am(q,t.ah.a(this.fZ(s.i(a,2))))\ncase 2:p=A.vC(s.i(a,3))\ns=s.i(a,2)\nif(s==null)s=t.K.a(s)\nreturn new A.bq(q,s,p!=null?new A.dI(p):null)\ncase 1:return new A.ba(q,t.O.a(this.fZ(s.i(a,2))))\ncase 3:return new A.bo(q)}throw A.a(B.aF)},\nh0(a){var s,r,q,p,o,n,m,l,k,j,i,h,g,f\nif(a==null)return a\nif(a instanceof A.d3)return a.a\nelse if(a instanceof A.bU){s=a.a\nr=a.b\nq=[]\nfor(p=a.c,o=p.length,n=0;n<p.length;p.length===o||(0,A.W)(p),++n)q.push(this.dG(p[n]))\nreturn[3,s.a,r,q,a.d]}else if(a instanceof A.bg){s=a.a\nr=[4,s.a]\nfor(s=s.b,q=s.length,n=0;n<s.length;s.length===q||(0,A.W)(s),++n){m=s[n]\np=[m.a]\nfor(o=m.b,l=o.length,k=0;k<o.length;o.length===l||(0,A.W)(o),++k)p.push(this.dG(o[k]))\nr.push(p)}r.push(a.b)\nreturn r}else if(a instanceof A.c3)return A.d([5,a.a.a,a.b],t.Y)\nelse if(a instanceof A.bT)return A.d([6,a.a,a.b],t.Y)\nelse if(a instanceof A.c4)return A.d([13,a.a.b],t.f)\nelse if(a instanceof A.c2){s=a.a\nreturn A.d([7,s.a,s.b,a.b],t.Y)}else if(a instanceof A.by){s=A.d([8],t.f)\nfor(r=a.a,q=r.length,n=0;n<r.length;r.length===q||(0,A.W)(r),++n){j=r[n]\np=j.b\no=j.a\ns.push([p,o==null?null:o.a])}return s}else if(a instanceof A.bA){i=a.a\ns=J.V(i)\nif(s.gF(i))return B.aK\nelse{h=[11]\ng=J.iU(s.gG(i).ga_())\nh.push(g.length)\nB.c.aJ(h,g)\nh.push(s.gl(i))\nfor(s=s.gt(i);s.k();)for(r=J.M(s.gm().gaP());r.k();)h.push(this.dG(r.gm()))\nreturn h}}else if(a instanceof A.c1)return A.d([12,a.a],t.t)\nelse if(a instanceof A.aH){f=a.a\n$label0$0:{if(A.bM(f)){s=f\nbreak $label0$0}if(A.bn(f)){s=A.d([10,f],t.t)\nbreak $label0$0}s=A.y(A.H(\"Unknown primitive response\"))}return s}},\nfZ(a8){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1,a2,a3,a4,a5,a6=null,a7={}\nif(a8==null)return a6\nif(A.bM(a8))return new A.aH(a8)\na7.a=null\nif(A.bn(a8)){s=a6\nr=a8}else{t.j.a(a8)\na7.a=a8\nr=A.h(J.aO(a8,0))\ns=a8}q=new A.jC(a7)\np=new A.jD(a7)\nswitch(r){case 0:return B.C\ncase 3:o=B.a8[q.$1(1)]\ns=a7.a\ns.toString\nn=A.ad(J.aO(s,2))\ns=J.cQ(t.j.a(J.aO(a7.a,3)),this.gi5(),t.X)\nreturn new A.bU(o,n,A.ay(s,!0,s.$ti.h(\"P.E\")),p.$1(4))\ncase 4:s.toString\nm=t.j\nn=J.py(m.a(J.aO(s,1)),t.N)\nl=A.d([],t.g7)\nfor(k=2;k<J.ae(a7.a)-1;++k){j=m.a(J.aO(a7.a,k))\ns=J.V(j)\ni=A.h(s.i(j,0))\nh=[]\nfor(s=s.X(j,1),g=s.$ti,s=new A.aZ(s,s.gl(0),g.h(\"aZ<P.E>\")),g=g.h(\"P.E\");s.k();){a8=s.d\nh.push(this.dE(a8==null?g.a(a8):a8))}l.push(new A.cR(i,h))}f=J.iS(a7.a)\n$label1$2:{if(f==null){s=a6\nbreak $label1$2}A.h(f)\ns=f\nbreak $label1$2}return new A.bg(new A.e1(n,l),s)\ncase 5:return new A.c3(B.aa[q.$1(1)],p.$1(2))\ncase 6:return new A.bT(q.$1(1),p.$1(2))\ncase 13:s.toString\nreturn new A.c4(A.or(B.ac,A.ad(J.aO(s,1))))\ncase 7:return new A.c2(new A.et(p.$1(1),q.$1(2)),q.$1(3))\ncase 8:e=A.d([],t.be)\ns=t.j\nk=1\nwhile(!0){m=a7.a\nm.toString\nif(!(k<J.ae(m)))break\nd=s.a(J.aO(a7.a,k))\nm=J.V(d)\nc=m.i(d,1)\n$label2$3:{if(c==null){i=a6\nbreak $label2$3}A.h(c)\ni=c\nbreak $label2$3}m=A.ad(m.i(d,0))\ne.push(new A.bC(i==null?a6:B.a7[i],m));++k}return new A.by(e)\ncase 11:s.toString\nif(J.ae(s)===1)return B.b_\nb=q.$1(1)\ns=2+b\nm=t.N\na=J.py(J.tI(a7.a,2,s),m)\na0=q.$1(s)\na1=A.d([],t.d)\nfor(s=a.a,i=J.V(s),h=a.$ti.y[1],g=3+b,a2=t.X,k=0;k<a0;++k){a3=g+k*b\na4=A.a3(m,a2)\nfor(a5=0;a5<b;++a5)a4.q(0,h.a(i.i(s,a5)),this.dE(J.aO(a7.a,a3+a5)))\na1.push(a4)}return new A.bA(a1)\ncase 12:return new A.c1(q.$1(1))\ncase 10:return new A.aH(A.h(J.aO(a8,1)))}throw A.a(A.ag(r,\"tag\",\"Tag was unknown\"))},\ndG(a){if(t.I.b(a)&&!t.p.b(a))return new Uint8Array(A.iJ(a))\nelse if(a instanceof A.a6)return A.d([\"bigint\",a.j(0)],t.s)\nelse return a},\ndE(a){var s\nif(t.j.b(a)){s=J.V(a)\nif(s.gl(a)===2&&J.X(s.i(a,0),\"bigint\"))return A.oU(J.aU(s.i(a,1)),null)\nreturn new Uint8Array(A.iJ(s.b8(a,t.S)))}return a}}\nA.jC.prototype={\n$1(a){var s=this.a.a\ns.toString\nreturn A.h(J.aO(s,a))},\n$S:12}\nA.jD.prototype={\n$1(a){var s,r=this.a.a\nr.toString\ns=J.aO(r,a)\n$label0$0:{if(s==null){r=null\nbreak $label0$0}A.h(s)\nr=s\nbreak $label0$0}return r},\n$S:88}\nA.bZ.prototype={}\nA.am.prototype={\nj(a){return\"Request (id = \"+this.a+\"): \"+A.u(this.b)}}\nA.ba.prototype={\nj(a){return\"SuccessResponse (id = \"+this.a+\"): \"+A.u(this.b)}}\nA.aH.prototype={$ibz:1}\nA.bq.prototype={\nj(a){return\"ErrorResponse (id = \"+this.a+\"): \"+A.u(this.b)+\" at \"+A.u(this.c)}}\nA.bo.prototype={\nj(a){return\"Previous request \"+this.a+\" was cancelled\"}}\nA.d3.prototype={\nae(){return\"NoArgsRequest.\"+this.b},\n$ias:1}\nA.cv.prototype={\nae(){return\"StatementMethod.\"+this.b}}\nA.bU.prototype={\nj(a){var s=this,r=s.d\nif(r!=null)return s.a.j(0)+\": \"+s.b+\" with \"+A.u(s.c)+\" (@\"+A.u(r)+\")\"\nreturn s.a.j(0)+\": \"+s.b+\" with \"+A.u(s.c)},\n$ias:1}\nA.c1.prototype={\nj(a){return\"Cancel previous request \"+this.a},\n$ias:1}\nA.bg.prototype={$ias:1}\nA.c0.prototype={\nae(){return\"NestedExecutorControl.\"+this.b}}\nA.c3.prototype={\nj(a){return\"RunTransactionAction(\"+this.a.j(0)+\", \"+A.u(this.b)+\")\"},\n$ias:1}\nA.bT.prototype={\nj(a){return\"EnsureOpen(\"+this.a+\", \"+A.u(this.b)+\")\"},\n$ias:1}\nA.c4.prototype={\nj(a){return\"ServerInfo(\"+this.a.j(0)+\")\"},\n$ias:1}\nA.c2.prototype={\nj(a){return\"RunBeforeOpen(\"+this.a.j(0)+\", \"+this.b+\")\"},\n$ias:1}\nA.by.prototype={\nj(a){return\"NotifyTablesUpdated(\"+A.u(this.a)+\")\"},\n$ias:1}\nA.bA.prototype={$ibz:1}\nA.kC.prototype={\nhM(a,b,c){this.Q.a.bF(new A.kH(this),t.P)},\nhw(a,b){var s,r,q=this\nif(q.y)throw A.a(A.B(\"Cannot add new channels after shutdown() was called\"))\ns=A.tW(a,b)\ns.hx(new A.kI(q,s))\nr=q.a.gao()\ns.bv(new A.am(s.hb(),new A.c4(r)))\nq.z.v(0,s)\nreturn s.w.a.bF(new A.kJ(q,s),t.H)},\nhy(){var s,r=this\nif(!r.y){r.y=!0\ns=r.a.p()\nr.Q.L(s)}return r.Q.a},\ni_(){var s,r,q\nfor(s=this.z,s=A.im(s,s.r,s.$ti.c),r=s.$ti.c;s.k();){q=s.d;(q==null?r.a(q):q).p()}},\nis(a,b){var s,r,q=this,p=b.b\nif(p instanceof A.d3)switch(p.a){case 0:s=A.B(\"Remote shutdowns not allowed\")\nthrow A.a(s)}else if(p instanceof A.bT)return q.bL(a,p)\nelse if(p instanceof A.bU){r=A.xr(new A.kD(q,p),t.O)\nq.r.q(0,b.a,r)\nreturn r.a.a.ai(new A.kE(q,b))}else if(p instanceof A.bg)return q.bT(p.a,p.b)\nelse if(p instanceof A.by){q.as.v(0,p)\nq.jM(p,a)}else if(p instanceof A.c3)return q.aH(a,p.a,p.b)\nelse if(p instanceof A.c1){s=q.r.i(0,p.a)\nif(s!=null)s.J()\nreturn null}return null},\nbL(a,b){return this.io(a,b)},\nio(a,b){var s=0,r=A.o(t.cc),q,p=this,o,n,m\nvar $async$bL=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:s=3\nreturn A.c(p.aF(b.b),$async$bL)\ncase 3:o=d\nn=b.a\np.f=n\nm=A\ns=4\nreturn A.c(o.ap(new A.f7(p,a,n)),$async$bL)\ncase 4:q=new m.aH(d)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$bL,r)},\naG(a,b,c,d){return this.j1(a,b,c,d)},\nj1(a,b,c,d){var s=0,r=A.o(t.O),q,p=this,o,n\nvar $async$aG=A.p(function(e,f){if(e===1)return A.l(f,r)\nwhile(true)switch(s){case 0:s=3\nreturn A.c(p.aF(d),$async$aG)\ncase 3:o=f\ns=4\nreturn A.c(A.pP(B.z,t.H),$async$aG)\ncase 4:A.rx()\ncase 5:switch(a.a){case 0:s=7\nbreak\ncase 1:s=8\nbreak\ncase 2:s=9\nbreak\ncase 3:s=10\nbreak\ndefault:s=6\nbreak}break\ncase 7:s=11\nreturn A.c(o.a8(b,c),$async$aG)\ncase 11:q=null\ns=1\nbreak\ncase 8:n=A\ns=12\nreturn A.c(o.cf(b,c),$async$aG)\ncase 12:q=new n.aH(f)\ns=1\nbreak\ncase 9:n=A\ns=13\nreturn A.c(o.aw(b,c),$async$aG)\ncase 13:q=new n.aH(f)\ns=1\nbreak\ncase 10:n=A\ns=14\nreturn A.c(o.ad(b,c),$async$aG)\ncase 14:q=new n.bA(f)\ns=1\nbreak\ncase 6:case 1:return A.m(q,r)}})\nreturn A.n($async$aG,r)},\nbT(a,b){return this.iZ(a,b)},\niZ(a,b){var s=0,r=A.o(t.O),q,p=this\nvar $async$bT=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:s=4\nreturn A.c(p.aF(b),$async$bT)\ncase 4:s=3\nreturn A.c(d.av(a),$async$bT)\ncase 3:q=null\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$bT,r)},\naF(a){return this.ix(a)},\nix(a){var s=0,r=A.o(t.x),q,p=this,o\nvar $async$aF=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:s=3\nreturn A.c(p.jj(a),$async$aF)\ncase 3:if(a!=null){o=p.d.i(0,a)\no.toString}else o=p.a\nq=o\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$aF,r)},\nbV(a,b){return this.jd(a,b)},\njd(a,b){var s=0,r=A.o(t.S),q,p=this,o\nvar $async$bV=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:s=3\nreturn A.c(p.aF(b),$async$bV)\ncase 3:o=d.cP()\ns=4\nreturn A.c(o.ap(new A.f7(p,a,p.f)),$async$bV)\ncase 4:q=p.dZ(o,!0)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$bV,r)},\nbU(a,b){return this.jc(a,b)},\njc(a,b){var s=0,r=A.o(t.S),q,p=this,o\nvar $async$bU=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:s=3\nreturn A.c(p.aF(b),$async$bU)\ncase 3:o=d.cO()\ns=4\nreturn A.c(o.ap(new A.f7(p,a,p.f)),$async$bU)\ncase 4:q=p.dZ(o,!0)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$bU,r)},\ndZ(a,b){var s,r,q=this.e++\nthis.d.q(0,q,a)\ns=this.w\nr=s.length\nif(r!==0)B.c.cY(s,0,q)\nelse s.push(q)\nreturn q},\naH(a,b,c){return this.jh(a,b,c)},\njh(a,b,c){var s=0,r=A.o(t.O),q,p=2,o,n=[],m=this,l,k\nvar $async$aH=A.p(function(d,e){if(d===1){o=e\ns=p}while(true)switch(s){case 0:s=b===B.ad?3:5\nbreak\ncase 3:k=A\ns=6\nreturn A.c(m.bV(a,c),$async$aH)\ncase 6:q=new k.aH(e)\ns=1\nbreak\ns=4\nbreak\ncase 5:s=b===B.ae?7:8\nbreak\ncase 7:k=A\ns=9\nreturn A.c(m.bU(a,c),$async$aH)\ncase 9:q=new k.aH(e)\ns=1\nbreak\ncase 8:case 4:s=10\nreturn A.c(m.aF(c),$async$aH)\ncase 10:l=e\ns=b===B.af?11:12\nbreak\ncase 11:s=13\nreturn A.c(l.p(),$async$aH)\ncase 13:c.toString\nm.cD(c)\nq=null\ns=1\nbreak\ncase 12:if(!t.u.b(l))throw A.a(A.ag(c,\"transactionId\",\"Does not reference a transaction. This might happen if you don't await all operations made inside a transaction, in which case the transaction might complete with pending operations.\"))\ncase 14:switch(b.a){case 1:s=16\nbreak\ncase 2:s=17\nbreak\ndefault:s=15\nbreak}break\ncase 16:s=18\nreturn A.c(l.bj(),$async$aH)\ncase 18:c.toString\nm.cD(c)\ns=15\nbreak\ncase 17:p=19\ns=22\nreturn A.c(l.bD(),$async$aH)\ncase 22:n.push(21)\ns=20\nbreak\ncase 19:n=[2]\ncase 20:p=2\nc.toString\nm.cD(c)\ns=n.pop()\nbreak\ncase 21:s=15\nbreak\ncase 15:q=null\ns=1\nbreak\ncase 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$aH,r)},\ncD(a){var s\nthis.d.A(0,a)\nB.c.A(this.w,a)\ns=this.x\nif((s.c&4)===0)s.v(0,null)},\njj(a){var s,r=new A.kG(this,a)\nif(r.$0())return A.aX(null,t.H)\ns=this.x\nreturn new A.eM(s,A.t(s).h(\"eM<1>\")).k0(0,new A.kF(r))},\njM(a,b){var s,r,q\nfor(s=this.z,s=A.im(s,s.r,s.$ti.c),r=s.$ti.c;s.k();){q=s.d\nif(q==null)q=r.a(q)\nif(q!==b)q.bv(new A.am(q.d++,a))}}}\nA.kH.prototype={\n$1(a){var s=this.a\ns.i_()\ns.as.p()},\n$S:89}\nA.kI.prototype={\n$1(a){return this.a.is(this.b,a)},\n$S:93}\nA.kJ.prototype={\n$1(a){return this.a.z.A(0,this.b)},\n$S:24}\nA.kD.prototype={\n$0(){var s=this.b\nreturn this.a.aG(s.a,s.b,s.c,s.d)},\n$S:110}\nA.kE.prototype={\n$0(){return this.a.r.A(0,this.b.a)},\n$S:116}\nA.kG.prototype={\n$0(){var s,r=this.b\nif(r==null)return this.a.w.length===0\nelse{s=this.a.w\nreturn s.length!==0&&B.c.gG(s)===r}},\n$S:22}\nA.kF.prototype={\n$1(a){return this.a.$0()},\n$S:24}\nA.f7.prototype={\ncN(a,b){return this.jC(a,b)},\njC(a,b){var s=0,r=A.o(t.H),q=1,p,o=[],n=this,m,l,k,j,i\nvar $async$cN=A.p(function(c,d){if(c===1){p=d\ns=q}while(true)switch(s){case 0:j=n.a\ni=j.dZ(a,!0)\nq=2\nm=n.b\nl=m.hb()\nk=new A.k($.i,t.D)\nm.e.q(0,l,new A.ir(new A.a2(k,t.h),A.oG()))\nm.bv(new A.am(l,new A.c2(b,i)))\ns=5\nreturn A.c(k,$async$cN)\ncase 5:o.push(4)\ns=3\nbreak\ncase 2:o=[1]\ncase 3:q=1\nj.cD(i)\ns=o.pop()\nbreak\ncase 4:return A.m(null,r)\ncase 1:return A.l(p,r)}})\nreturn A.n($async$cN,r)}}\nA.hX.prototype={\ndk(a){var s,r,q\n$label0$0:{if(a instanceof A.am){s=new A.ap(0,{i:a.a,p:this.j4(a.b)})\nbreak $label0$0}if(a instanceof A.ba){s=new A.ap(1,{i:a.a,p:this.j5(a.b)})\nbreak $label0$0}if(a instanceof A.bq){r=a.c\nq=J.aU(a.b)\ns=r==null?null:r.j(0)\ns=new A.ap(2,[a.a,q,s])\nbreak $label0$0}if(a instanceof A.bo){s=new A.ap(3,a.a)\nbreak $label0$0}s=null}return A.d([s.a,s.b],t.f)},\nej(a){var s,r,q,p,o,n,m=null,l=\"Pattern matching error\",k={}\nk.a=null\ns=a.length===2\nif(s){r=a[0]\nq=k.a=a[1]}else{q=m\nr=q}if(!s)throw A.a(A.B(l))\nr=A.h(A.r(r))\n$label0$0:{if(0===r){s=new A.lK(k,this).$0()\nbreak $label0$0}if(1===r){s=new A.lL(k,this).$0()\nbreak $label0$0}if(2===r){t.c.a(q)\ns=q.length===3\np=m\no=m\nif(s){n=q[0]\np=q[1]\no=q[2]}else n=m\nif(!s)A.y(A.B(l))\nn=A.h(A.r(n))\nA.ad(p)\ns=new A.bq(n,p,o!=null?new A.dI(A.ad(o)):m)\nbreak $label0$0}if(3===r){s=new A.bo(A.h(A.r(q)))\nbreak $label0$0}s=A.y(A.K(\"Unknown message tag \"+r,m))}return s},\nj4(a){var s,r,q,p,o,n,m,l,k,j,i,h=null\n$label0$0:{s=h\nif(a==null)break $label0$0\nif(a instanceof A.bU){s=a.a\nr=a.b\nq=[]\nfor(p=a.c,o=p.length,n=0;n<p.length;p.length===o||(0,A.W)(p),++n)q.push(this.e8(p[n]))\np=a.d\nif(p==null)p=h\np=[3,s.a,r,q,p]\ns=p\nbreak $label0$0}if(a instanceof A.c1){s=A.d([12,a.a],t.n)\nbreak $label0$0}if(a instanceof A.bg){s=a.a\nq=J.cQ(s.a,new A.lI(),t.N)\nq=[4,A.ay(q,!0,q.$ti.h(\"P.E\"))]\nfor(s=s.b,p=s.length,n=0;n<s.length;s.length===p||(0,A.W)(s),++n){m=s[n]\no=[m.a]\nfor(l=m.b,k=l.length,j=0;j<l.length;l.length===k||(0,A.W)(l),++j)o.push(this.e8(l[j]))\nq.push(o)}s=a.b\nq.push(s==null?h:s)\ns=q\nbreak $label0$0}if(a instanceof A.c3){s=a.a\nq=a.b\nif(q==null)q=h\nq=A.d([5,s.a,q],t.r)\ns=q\nbreak $label0$0}if(a instanceof A.bT){r=a.a\ns=a.b\ns=A.d([6,r,s==null?h:s],t.r)\nbreak $label0$0}if(a instanceof A.c4){s=A.d([13,a.a.b],t.f)\nbreak $label0$0}if(a instanceof A.c2){s=a.a\nq=s.a\nif(q==null)q=h\ns=A.d([7,q,s.b,a.b],t.r)\nbreak $label0$0}if(a instanceof A.by){s=[8]\nfor(q=a.a,p=q.length,n=0;n<q.length;q.length===p||(0,A.W)(q),++n){i=q[n]\nr=i.b\no=i.a\ns.push([r,o==null?h:o.a])}break $label0$0}if(B.C===a){s=0\nbreak $label0$0}}return s},\ni8(a){var s,r,q,p,o,n,m=null\nif(a==null)return m\nif(typeof a===\"number\")return B.C\ns=t.c\ns.a(a)\nr=A.h(A.r(a[0]))\n$label0$0:{if(3===r){q=B.a8[A.h(A.r(a[1]))]\np=A.ad(a[2])\no=[]\nn=s.a(a[3])\ns=B.c.gt(n)\nfor(;s.k();)o.push(this.e7(s.gm()))\ns=a[4]\ns=new A.bU(q,p,o,s==null?m:A.h(A.r(s)))\nbreak $label0$0}if(12===r){s=new A.c1(A.h(A.r(a[1])))\nbreak $label0$0}if(4===r){s=new A.lE(this,a).$0()\nbreak $label0$0}if(5===r){s=B.aa[A.h(A.r(a[1]))]\nq=a[2]\ns=new A.c3(s,q==null?m:A.h(A.r(q)))\nbreak $label0$0}if(6===r){s=A.h(A.r(a[1]))\nq=a[2]\ns=new A.bT(s,q==null?m:A.h(A.r(q)))\nbreak $label0$0}if(13===r){s=new A.c4(A.or(B.ac,A.ad(a[1])))\nbreak $label0$0}if(7===r){s=a[1]\ns=s==null?m:A.h(A.r(s))\ns=new A.c2(new A.et(s,A.h(A.r(a[2]))),A.h(A.r(a[3])))\nbreak $label0$0}if(8===r){s=B.c.X(a,1)\nq=s.$ti.h(\"D<P.E,bC>\")\nq=new A.by(A.ay(new A.D(s,new A.lD(),q),!0,q.h(\"P.E\")))\ns=q\nbreak $label0$0}s=A.y(A.K(\"Unknown request tag \"+r,m))}return s},\nj5(a){var s,r\n$label0$0:{s=null\nif(a==null)break $label0$0\nif(a instanceof A.aH){r=a.a\ns=A.bM(r)?r:A.h(r)\nbreak $label0$0}if(a instanceof A.bA){s=this.j6(a)\nbreak $label0$0}}return s},\nj6(a){var s,r,q,p=a.a,o=J.V(p)\nif(o.gF(p)){p=self\nreturn{c:new p.Array(),r:new p.Array()}}else{s=J.cQ(o.gG(p).ga_(),new A.lJ(),t.N).cj(0)\nr=A.d([],t.fk)\nfor(p=o.gt(p);p.k();){q=[]\nfor(o=J.M(p.gm().gaP());o.k();)q.push(this.e8(o.gm()))\nr.push(q)}return{c:s,r:r}}},\ni9(a){var s,r,q,p,o,n,m,l,k,j\nif(a==null)return null\nelse if(typeof a===\"boolean\")return new A.aH(A.bJ(a))\nelse if(typeof a===\"number\")return new A.aH(A.h(A.r(a)))\nelse{t.m.a(a)\ns=a.c\ns=t.o.b(s)?s:new A.ah(s,A.Q(s).h(\"ah<1,j>\"))\nr=t.N\ns=J.cQ(s,new A.lH(),r)\nq=A.ay(s,!0,s.$ti.h(\"P.E\"))\np=A.d([],t.d)\ns=a.r\ns=J.M(t.e9.b(s)?s:new A.ah(s,A.Q(s).h(\"ah<1,w<e?>>\")))\no=t.X\nfor(;s.k();){n=s.gm()\nm=A.a3(r,o)\nn=A.ua(n,0,o)\nl=J.M(n.a)\nn=n.b\nk=new A.eg(l,n)\nfor(;k.k();){j=k.c\nj=j>=0?new A.ap(n+j,l.gm()):A.y(A.ak())\nm.q(0,q[j.a],this.e7(j.b))}p.push(m)}return new A.bA(p)}},\ne8(a){var s\n$label0$0:{if(a==null){s=null\nbreak $label0$0}if(A.bn(a)){s=a\nbreak $label0$0}if(A.bM(a)){s=a\nbreak $label0$0}if(typeof a==\"string\"){s=a\nbreak $label0$0}if(typeof a==\"number\"){s=A.d([15,a],t.n)\nbreak $label0$0}if(a instanceof A.a6){s=A.d([14,a.j(0)],t.f)\nbreak $label0$0}if(t.I.b(a)){s=new Uint8Array(A.iJ(a))\nbreak $label0$0}s=A.y(A.K(\"Unknown db value: \"+A.u(a),null))}return s},\ne7(a){var s,r,q,p=null\nif(a!=null)if(typeof a===\"number\")return A.h(A.r(a))\nelse if(typeof a===\"boolean\")return A.bJ(a)\nelse if(typeof a===\"string\")return A.ad(a)\nelse if(A.oy(a,\"Uint8Array\"))return t.Z.a(a)\nelse{t.c.a(a)\ns=a.length===2\nif(s){r=a[0]\nq=a[1]}else{q=p\nr=q}if(!s)throw A.a(A.B(\"Pattern matching error\"))\nif(r==14)return A.oU(A.ad(q),p)\nelse return A.r(q)}else return p}}\nA.lK.prototype={\n$0(){var s=t.m.a(this.a.a)\nreturn new A.am(s.i,this.b.i8(s.p))},\n$S:38}\nA.lL.prototype={\n$0(){var s=t.m.a(this.a.a)\nreturn new A.ba(s.i,this.b.i9(s.p))},\n$S:37}\nA.lI.prototype={\n$1(a){return a},\n$S:8}\nA.lE.prototype={\n$0(){var s,r,q,p,o,n,m=this.b,l=J.V(m),k=t.c,j=k.a(l.i(m,1)),i=t.o.b(j)?j:new A.ah(j,A.Q(j).h(\"ah<1,j>\"))\ni=J.cQ(i,new A.lF(),t.N)\ns=A.ay(i,!0,i.$ti.h(\"P.E\"))\ni=l.gl(m)\nr=A.d([],t.g7)\nfor(i=l.X(m,2).ah(0,i-3),k=A.e4(i,i.$ti.h(\"f.E\"),k),k=A.en(k,new A.lG(),A.t(k).h(\"f.E\"),t.ee),i=A.t(k),k=new A.b0(J.M(k.a),k.b,i.h(\"b0<1,2>\")),q=this.a.gjk(),i=i.y[1];k.k();){p=k.a\nif(p==null)p=i.a(p)\no=J.V(p)\nn=A.h(A.r(o.i(p,0)))\np=o.X(p,1)\no=p.$ti.h(\"D<P.E,e?>\")\nr.push(new A.cR(n,A.ay(new A.D(p,q,o),!0,o.h(\"P.E\"))))}m=l.i(m,l.gl(m)-1)\nm=m==null?null:A.h(A.r(m))\nreturn new A.bg(new A.e1(s,r),m)},\n$S:40}\nA.lF.prototype={\n$1(a){return a},\n$S:8}\nA.lG.prototype={\n$1(a){return a},\n$S:41}\nA.lD.prototype={\n$1(a){var s,r,q\nt.c.a(a)\ns=a.length===2\nif(s){r=a[0]\nq=a[1]}else{r=null\nq=null}if(!s)throw A.a(A.B(\"Pattern matching error\"))\nA.ad(r)\nreturn new A.bC(q==null?null:B.a7[A.h(A.r(q))],r)},\n$S:42}\nA.lJ.prototype={\n$1(a){return a},\n$S:8}\nA.lH.prototype={\n$1(a){return a},\n$S:8}\nA.di.prototype={\nae(){return\"UpdateKind.\"+this.b}}\nA.bC.prototype={\ngB(a){return A.es(this.a,this.b,B.f,B.f)},\nO(a,b){if(b==null)return!1\nreturn b instanceof A.bC&&b.a==this.a&&b.b===this.b},\nj(a){return\"TableUpdate(\"+this.b+\", kind: \"+A.u(this.a)+\")\"}}\nA.og.prototype={\n$0(){return this.a.a.a.L(A.jW(this.b,this.c))},\n$S:0}\nA.bS.prototype={\nJ(){var s,r\nif(this.c)return\nfor(s=this.b,r=0;!1;++r)s[r].$0()\nthis.c=!0}}\nA.e3.prototype={\nj(a){return\"Operation was cancelled\"},\n$ia5:1}\nA.al.prototype={\np(){var s=0,r=A.o(t.H)\nvar $async$p=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:return A.m(null,r)}})\nreturn A.n($async$p,r)}}\nA.e1.prototype={\ngB(a){return A.es(B.o.h6(this.a),B.o.h6(this.b),B.f,B.f)},\nO(a,b){if(b==null)return!1\nreturn b instanceof A.e1&&B.o.em(b.a,this.a)&&B.o.em(b.b,this.b)},\nj(a){return\"BatchedStatements(\"+A.u(this.a)+\", \"+A.u(this.b)+\")\"}}\nA.cR.prototype={\ngB(a){return A.es(this.a,B.o,B.f,B.f)},\nO(a,b){if(b==null)return!1\nreturn b instanceof A.cR&&b.a===this.a&&B.o.em(b.b,this.b)},\nj(a){return\"ArgumentsForBatchedStatement(\"+this.a+\", \"+A.u(this.b)+\")\"}}\nA.jq.prototype={}\nA.kq.prototype={}\nA.lb.prototype={}\nA.kk.prototype={}\nA.ju.prototype={}\nA.hm.prototype={}\nA.jJ.prototype={}\nA.i2.prototype={\ngez(){return!1},\ngc6(){return!1},\nb6(a,b){if(this.gez()||this.b>0)return this.a.cr(new A.lT(a,b),b)\nelse return a.$0()},\ncz(a,b){this.gc6()},\nad(a,b){return this.kB(a,b)},\nkB(a,b){var s=0,r=A.o(t.aS),q,p=this,o\nvar $async$ad=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:s=3\nreturn A.c(p.b6(new A.lY(p,a,b),t.aj),$async$ad)\ncase 3:o=d.gjB(0)\nq=A.ay(o,!0,o.$ti.h(\"P.E\"))\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$ad,r)},\ncf(a,b){return this.b6(new A.lW(this,a,b),t.S)},\naw(a,b){return this.b6(new A.lX(this,a,b),t.S)},\na8(a,b){return this.b6(new A.lV(this,b,a),t.H)},\nkx(a){return this.a8(a,null)},\nav(a){return this.b6(new A.lU(this,a),t.H)},\ncO(){return new A.eV(this,new A.a2(new A.k($.i,t.D),t.h),new A.bh())},\ncP(){return this.aU(this)}}\nA.lT.prototype={\n$0(){A.rx()\nreturn this.a.$0()},\n$S(){return this.b.h(\"C<0>()\")}}\nA.lY.prototype={\n$0(){var s=this.a,r=this.b,q=this.c\ns.cz(r,q)\nreturn s.gaM().ad(r,q)},\n$S:43}\nA.lW.prototype={\n$0(){var s=this.a,r=this.b,q=this.c\ns.cz(r,q)\nreturn s.gaM().d8(r,q)},\n$S:36}\nA.lX.prototype={\n$0(){var s=this.a,r=this.b,q=this.c\ns.cz(r,q)\nreturn s.gaM().aw(r,q)},\n$S:36}\nA.lV.prototype={\n$0(){var s,r,q=this.b\nif(q==null)q=B.t\ns=this.a\nr=this.c\ns.cz(r,q)\nreturn s.gaM().a8(r,q)},\n$S:3}\nA.lU.prototype={\n$0(){var s=this.a\ns.gc6()\nreturn s.gaM().av(this.b)},\n$S:3}\nA.iE.prototype={\nhZ(){this.c=!0\nif(this.d)throw A.a(A.B(\"A transaction was used after being closed. Please check that you're awaiting all database operations inside a `transaction` block.\"))},\naU(a){throw A.a(A.H(\"Nested transactions aren't supported.\"))},\ngao(){return B.m},\ngc6(){return!1},\ngez(){return!0},\n$ihG:1}\nA.fb.prototype={\nap(a){var s,r,q=this\nq.hZ()\ns=q.z\nif(s==null){s=q.z=new A.a2(new A.k($.i,t.k),t.co)\nr=q.as;++r.b\nr.b6(new A.nn(q),t.P).ai(new A.no(r))}return s.a},\ngaM(){return this.e.e},\naU(a){var s=this.at+1\nreturn new A.fb(this.y,new A.a2(new A.k($.i,t.D),t.h),a,s,A.rd(s),A.rb(s),A.rc(s),this.e,new A.bh())},\nbj(){var s=0,r=A.o(t.H),q,p=this\nvar $async$bj=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:if(!p.c){s=1\nbreak}s=3\nreturn A.c(p.a8(p.ay,B.t),$async$bj)\ncase 3:p.f2()\ncase 1:return A.m(q,r)}})\nreturn A.n($async$bj,r)},\nbD(){var s=0,r=A.o(t.H),q,p=2,o,n=[],m=this\nvar $async$bD=A.p(function(a,b){if(a===1){o=b\ns=p}while(true)switch(s){case 0:if(!m.c){s=1\nbreak}p=3\ns=6\nreturn A.c(m.a8(m.ch,B.t),$async$bD)\ncase 6:n.push(5)\ns=4\nbreak\ncase 3:n=[2]\ncase 4:p=2\nm.f2()\ns=n.pop()\nbreak\ncase 5:case 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$bD,r)},\nf2(){var s=this\nif(s.at===0)s.e.e.a=!1\ns.Q.aV()\ns.d=!0}}\nA.nn.prototype={\n$0(){var s=0,r=A.o(t.P),q=1,p,o=this,n,m,l,k,j\nvar $async$$0=A.p(function(a,b){if(a===1){p=b\ns=q}while(true)switch(s){case 0:q=3\nl=o.a\ns=6\nreturn A.c(l.kx(l.ax),$async$$0)\ncase 6:l.e.e.a=!0\nl.z.L(!0)\nq=1\ns=5\nbreak\ncase 3:q=2\nj=p\nn=A.E(j)\nm=A.R(j)\no.a.z.bx(n,m)\ns=5\nbreak\ncase 2:s=1\nbreak\ncase 5:s=7\nreturn A.c(o.a.Q.a,$async$$0)\ncase 7:return A.m(null,r)\ncase 1:return A.l(p,r)}})\nreturn A.n($async$$0,r)},\n$S:14}\nA.no.prototype={\n$0(){return this.a.b--},\n$S:46}\nA.fQ.prototype={\ngaM(){return this.e},\ngao(){return B.m},\nap(a){return this.x.cr(new A.jz(this,a),t.y)},\nbt(a){return this.j0(a)},\nj0(a){var s=0,r=A.o(t.H),q=this,p,o,n,m\nvar $async$bt=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:n=q.e\nm=n.y\nm===$&&A.G()\np=a.c\ns=m instanceof A.hm?2:4\nbreak\ncase 2:o=p\ns=3\nbreak\ncase 4:s=m instanceof A.f9?5:7\nbreak\ncase 5:s=8\nreturn A.c(A.aX(m.a.gkG(),t.S),$async$bt)\ncase 8:o=c\ns=6\nbreak\ncase 7:throw A.a(A.jL(\"Invalid delegate: \"+n.j(0)+\". The versionDelegate getter must not subclass DBVersionDelegate directly\"))\ncase 6:case 3:if(o===0)o=null\ns=9\nreturn A.c(a.cN(new A.i3(q,new A.bh()),new A.et(o,p)),$async$bt)\ncase 9:s=m instanceof A.f9&&o!==p?10:11\nbreak\ncase 10:m.a.h1(\"PRAGMA user_version = \"+p+\";\")\ns=12\nreturn A.c(A.aX(null,t.H),$async$bt)\ncase 12:case 11:return A.m(null,r)}})\nreturn A.n($async$bt,r)},\naU(a){var s=$.i\nreturn new A.fb(B.az,new A.a2(new A.k(s,t.D),t.h),a,0,\"BEGIN TRANSACTION\",\"COMMIT TRANSACTION\",\"ROLLBACK TRANSACTION\",this,new A.bh())},\np(){return this.x.cr(new A.jy(this),t.H)},\ngc6(){return this.r},\ngez(){return this.w}}\nA.jz.prototype={\n$0(){var s=0,r=A.o(t.y),q,p=2,o,n=this,m,l,k,j,i,h,g,f,e\nvar $async$$0=A.p(function(a,b){if(a===1){o=b\ns=p}while(true)switch(s){case 0:f=n.a\nif(f.d){q=A.pQ(new A.b2(\"Can't re-open a database after closing it. Please create a new database connection and open that instead.\"),null,t.y)\ns=1\nbreak}k=f.f\nif(k!=null)A.pM(k.a,k.b)\nj=f.e\ni=t.y\nh=A.aX(j.d,i)\ns=3\nreturn A.c(t.bF.b(h)?h:A.eX(h,i),$async$$0)\ncase 3:if(b){q=f.c=!0\ns=1\nbreak}i=n.b\ns=4\nreturn A.c(j.ca(i),$async$$0)\ncase 4:f.c=!0\np=6\ns=9\nreturn A.c(f.bt(i),$async$$0)\ncase 9:q=!0\ns=1\nbreak\np=2\ns=8\nbreak\ncase 6:p=5\ne=o\nm=A.E(e)\nl=A.R(e)\nf.f=new A.ap(m,l)\nthrow e\ns=8\nbreak\ncase 5:s=2\nbreak\ncase 8:case 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$$0,r)},\n$S:47}\nA.jy.prototype={\n$0(){var s=this.a\nif(s.c&&!s.d){s.d=!0\ns.c=!1\nreturn s.e.p()}else return A.aX(null,t.H)},\n$S:3}\nA.i3.prototype={\naU(a){return this.e.aU(a)},\nap(a){this.c=!0\nreturn A.aX(!0,t.y)},\ngaM(){return this.e.e},\ngc6(){return!1},\ngao(){return B.m}}\nA.eV.prototype={\ngao(){return this.e.gao()},\nap(a){var s,r,q,p=this,o=p.f\nif(o!=null)return o.a\nelse{p.c=!0\ns=new A.k($.i,t.k)\nr=new A.a2(s,t.co)\np.f=r\nq=p.e;++q.b\nq.b6(new A.mg(p,r),t.P)\nreturn s}},\ngaM(){return this.e.gaM()},\naU(a){return this.e.aU(a)},\np(){this.r.aV()\nreturn A.aX(null,t.H)}}\nA.mg.prototype={\n$0(){var s=0,r=A.o(t.P),q=this,p\nvar $async$$0=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:q.b.L(!0)\np=q.a\ns=2\nreturn A.c(p.r.a,$async$$0)\ncase 2:--p.e.b\nreturn A.m(null,r)}})\nreturn A.n($async$$0,r)},\n$S:14}\nA.d6.prototype={\ngjB(a){var s=this.b\nreturn new A.D(s,new A.ks(this),A.Q(s).h(\"D<1,aa<j,@>>\"))}}\nA.ks.prototype={\n$1(a){var s,r,q,p,o,n,m,l=A.a3(t.N,t.z)\nfor(s=this.a,r=s.a,q=r.length,s=s.c,p=J.V(a),o=0;o<r.length;r.length===q||(0,A.W)(r),++o){n=r[o]\nm=s.i(0,n)\nm.toString\nl.q(0,n,p.i(a,m))}return l},\n$S:48}\nA.kr.prototype={}\nA.dx.prototype={\ncP(){var s=this.a\nreturn new A.ik(s.aU(s),this.b)},\ncO(){return new A.dx(new A.eV(this.a,new A.a2(new A.k($.i,t.D),t.h),new A.bh()),this.b)},\ngao(){return this.a.gao()},\nap(a){return this.a.ap(a)},\nav(a){return this.a.av(a)},\na8(a,b){return this.a.a8(a,b)},\ncf(a,b){return this.a.cf(a,b)},\naw(a,b){return this.a.aw(a,b)},\nad(a,b){return this.a.ad(a,b)},\np(){return this.b.c2(this.a)}}\nA.ik.prototype={\nbD(){return t.u.a(this.a).bD()},\nbj(){return t.u.a(this.a).bj()},\n$ihG:1}\nA.et.prototype={}\nA.cu.prototype={\nae(){return\"SqlDialect.\"+this.b}}\nA.ey.prototype={\nca(a){return this.ki(a)},\nki(a){var s=0,r=A.o(t.H),q,p=this,o,n\nvar $async$ca=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:if(!p.c){o=p.kk()\np.b=o\ntry{A.tX(o)\nif(p.r){o=p.b\no.toString\no=new A.f9(o)}else o=B.aA\np.y=o\np.c=!0}catch(m){o=p.b\nif(o!=null)o.a7()\np.b=null\np.x.b.c1(0)\nthrow m}}p.d=!0\nq=A.aX(null,t.H)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$ca,r)},\np(){var s=0,r=A.o(t.H),q=this\nvar $async$p=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:q.x.jN()\nreturn A.m(null,r)}})\nreturn A.n($async$p,r)},\nkv(a){var s,r,q,p,o,n,m,l,k,j,i,h=A.d([],t.cf)\ntry{for(o=J.M(a.a);o.k();){s=o.gm()\nJ.on(h,this.b.d4(s,!0))}for(o=a.b,n=o.length,m=0;m<o.length;o.length===n||(0,A.W)(o),++m){r=o[m]\nq=J.aO(h,r.a)\nl=q\nk=r.b\nj=l.c\nif(j.d)A.y(A.B(u.D))\nif(!j.c){i=j.b\nA.h(A.r(i.c.id.call(null,i.b)))\nj.c=!0}j.b.ba()\nl.dt(new A.cr(k))\nl.ff()}}finally{for(o=h,n=o.length,m=0;m<o.length;o.length===n||(0,A.W)(o),++m){p=o[m]\nl=p\nk=l.c\nif(!k.d){j=$.dY().a\nif(j!=null)j.unregister(l)\nif(!k.d){k.d=!0\nif(!k.c){j=k.b\nA.h(A.r(j.c.id.call(null,j.b)))\nk.c=!0}j=k.b\nj.ba()\nA.h(A.r(j.c.to.call(null,j.b)))}l=l.b\nif(!l.e)B.c.A(l.c.d,k)}}}},\nkD(a,b){var s,r,q,p\nif(b.length===0)this.b.h1(a)\nelse{s=null\nr=null\nq=this.fj(a)\ns=q.a\nr=q.b\ntry{s.h2(new A.cr(b))}finally{p=s\nif(!r)p.a7()}}},\nad(a,b){return this.kA(a,b)},\nkA(a,b){var s=0,r=A.o(t.aj),q,p=[],o=this,n,m,l,k,j\nvar $async$ad=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:l=null\nk=null\nj=o.fj(a)\nl=j.a\nk=j.b\ntry{n=l.eR(new A.cr(b))\nm=A.uA(J.iU(n))\nq=m\ns=1\nbreak}finally{m=l\nif(!k)m.a7()}case 1:return A.m(q,r)}})\nreturn A.n($async$ad,r)},\nfj(a){var s,r,q,p=this.x.b,o=p.A(0,a),n=o!=null\nif(n)p.q(0,a,o)\nif(n)return new A.ap(o,!0)\ns=this.b.d4(a,!0)\nn=s.a\nr=n.b\nn=n.c.jZ\nif(A.h(A.r(n.call(null,r)))===0){if(p.a===64){q=p.A(0,new A.b8(p,A.t(p).h(\"b8<1>\")).gG(0))\nq.toString\nq.a7()}p.q(0,a,s)}return new A.ap(s,A.h(A.r(n.call(null,r)))===0)}}\nA.f9.prototype={}\nA.ko.prototype={\njN(){var s,r,q,p,o,n\nfor(s=this.b,r=s.gaP(),q=A.t(r),r=new A.b0(J.M(r.a),r.b,q.h(\"b0<1,2>\")),q=q.y[1];r.k();){p=r.a\nif(p==null)p=q.a(p)\no=p.c\nif(!o.d){n=$.dY().a\nif(n!=null)n.unregister(p)\nif(!o.d){o.d=!0\nif(!o.c){n=o.b\nA.h(A.r(n.c.id.call(null,n.b)))\no.c=!0}n=o.b\nn.ba()\nA.h(A.r(n.c.to.call(null,n.b)))}p=p.b\nif(!p.e)B.c.A(p.c.d,o)}}s.c1(0)}}\nA.jK.prototype={\n$1(a){return Date.now()},\n$S:49}\nA.nX.prototype={\n$1(a){var s=a.i(0,0)\nif(typeof s==\"number\")return this.a.$1(s)\nelse return null},\n$S:26}\nA.hc.prototype={\ngi7(){var s=this.a\ns===$&&A.G()\nreturn s},\ngao(){if(this.b){var s=this.a\ns===$&&A.G()\ns=B.m!==s.gao()}else s=!1\nif(s)throw A.a(A.jL(\"LazyDatabase created with \"+B.m.j(0)+\", but underlying database is \"+this.gi7().gao().j(0)+\".\"))\nreturn B.m},\nhV(){var s,r,q=this\nif(q.b)return A.aX(null,t.H)\nelse{s=q.d\nif(s!=null)return s.a\nelse{s=new A.k($.i,t.D)\nr=q.d=new A.a2(s,t.h)\nA.jW(q.e,t.x).bG(new A.kc(q,r),r.gjI(),t.P)\nreturn s}}},\ncO(){var s=this.a\ns===$&&A.G()\nreturn s.cO()},\ncP(){var s=this.a\ns===$&&A.G()\nreturn s.cP()},\nap(a){return this.hV().bF(new A.kd(this,a),t.y)},\nav(a){var s=this.a\ns===$&&A.G()\nreturn s.av(a)},\na8(a,b){var s=this.a\ns===$&&A.G()\nreturn s.a8(a,b)},\ncf(a,b){var s=this.a\ns===$&&A.G()\nreturn s.cf(a,b)},\naw(a,b){var s=this.a\ns===$&&A.G()\nreturn s.aw(a,b)},\nad(a,b){var s=this.a\ns===$&&A.G()\nreturn s.ad(a,b)},\np(){if(this.b){var s=this.a\ns===$&&A.G()\nreturn s.p()}else return A.aX(null,t.H)}}\nA.kc.prototype={\n$1(a){var s=this.a\ns.a!==$&&A.pq()\ns.a=a\ns.b=!0\nthis.b.aV()},\n$S:51}\nA.kd.prototype={\n$1(a){var s=this.a.a\ns===$&&A.G()\nreturn s.ap(this.b)},\n$S:52}\nA.bh.prototype={\ncr(a,b){var s=this.a,r=new A.k($.i,t.D)\nthis.a=r\nr=new A.kg(a,new A.a2(r,t.h),b)\nif(s!=null)return s.bF(new A.kh(r,b),b)\nelse return r.$0()}}\nA.kg.prototype={\n$0(){return A.jW(this.a,this.c).ai(this.b.gjH())},\n$S(){return this.c.h(\"C<0>()\")}}\nA.kh.prototype={\n$1(a){return this.a.$0()},\n$S(){return this.b.h(\"C<0>(~)\")}}\nA.lA.prototype={\n$1(a){var s,r=this,q=a.data\nif(r.a&&J.X(q,\"_disconnect\")){s=r.b.a\ns===$&&A.G()\ns=s.a\ns===$&&A.G()\ns.p()}else{s=r.b.a\nif(r.c){s===$&&A.G()\ns=s.a\ns===$&&A.G()\ns.v(0,B.a3.ej(t.c.a(q)))}else{s===$&&A.G()\ns=s.a\ns===$&&A.G()\ns.v(0,A.ry(q))}}},\n$S:10}\nA.lB.prototype={\n$1(a){var s=this.b\nif(this.a)s.postMessage(B.a3.dk(t.fJ.a(a)))\nelse s.postMessage(A.xe(a))},\n$S:7}\nA.lC.prototype={\n$0(){if(this.a)this.b.postMessage(\"_disconnect\")\nthis.b.close()},\n$S:0}\nA.jv.prototype={\nT(){A.aB(this.a,\"message\",new A.jx(this),!1)},\nak(a){return this.ir(a)},\nir(a6){var s=0,r=A.o(t.H),q=1,p,o=this,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1,a2,a3,a4,a5\nvar $async$ak=A.p(function(a7,a8){if(a7===1){p=a8\ns=q}while(true)switch(s){case 0:a3={}\nk=a6 instanceof A.da\nj=k?a6.a:null\ns=k?3:4\nbreak\ncase 3:a3.a=a3.b=!1\ns=5\nreturn A.c(o.b.cr(new A.jw(a3,o),t.P),$async$ak)\ncase 5:i=o.c.a.i(0,j)\nh=A.d([],t.L)\ng=!1\ns=a3.b?6:7\nbreak\ncase 6:a5=J\ns=8\nreturn A.c(A.dW(),$async$ak)\ncase 8:k=a5.M(a8)\ncase 9:if(!k.k()){s=10\nbreak}f=k.gm()\nh.push(new A.ap(B.F,f))\nif(f===j)g=!0\ns=9\nbreak\ncase 10:case 7:s=i!=null?11:13\nbreak\ncase 11:k=i.a\ne=k===B.w||k===B.E\ng=k===B.ak||k===B.al\ns=12\nbreak\ncase 13:a5=a3.a\nif(a5){s=14\nbreak}else a8=a5\ns=15\nbreak\ncase 14:s=16\nreturn A.c(A.dU(j),$async$ak)\ncase 16:case 15:e=a8\ncase 12:k=t.m.a(self)\nd=\"Worker\" in k\nf=a3.b\nc=a3.a\nnew A.e9(d,f,\"SharedArrayBuffer\" in k,c,h,B.v,e,g).di(o.a)\ns=2\nbreak\ncase 4:if(a6 instanceof A.dc){o.c.eT(a6)\ns=2\nbreak}k=a6 instanceof A.eB\nb=k?a6.a:null\ns=k?17:18\nbreak\ncase 17:s=19\nreturn A.c(A.hR(b),$async$ak)\ncase 19:a=a8\no.a.postMessage(!0)\ns=20\nreturn A.c(a.T(),$async$ak)\ncase 20:s=2\nbreak\ncase 18:n=null\nm=null\na0=a6 instanceof A.fR\nif(a0){a1=a6.a\nn=a1.a\nm=a1.b}s=a0?21:22\nbreak\ncase 21:q=24\ncase 27:switch(n){case B.am:s=29\nbreak\ncase B.F:s=30\nbreak\ndefault:s=28\nbreak}break\ncase 29:s=31\nreturn A.c(A.o2(m),$async$ak)\ncase 31:s=28\nbreak\ncase 30:s=32\nreturn A.c(A.fr(m),$async$ak)\ncase 32:s=28\nbreak\ncase 28:a6.di(o.a)\nq=1\ns=26\nbreak\ncase 24:q=23\na4=p\nl=A.E(a4)\nnew A.dm(J.aU(l)).di(o.a)\ns=26\nbreak\ncase 23:s=1\nbreak\ncase 26:s=2\nbreak\ncase 22:s=2\nbreak\ncase 2:return A.m(null,r)\ncase 1:return A.l(p,r)}})\nreturn A.n($async$ak,r)}}\nA.jx.prototype={\n$1(a){this.a.ak(A.oL(t.m.a(a.data)))},\n$S:1}\nA.jw.prototype={\n$0(){var s=0,r=A.o(t.P),q=this,p,o,n,m,l\nvar $async$$0=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:o=q.b\nn=o.d\nm=q.a\ns=n!=null?2:4\nbreak\ncase 2:m.b=n.b\nm.a=n.a\ns=3\nbreak\ncase 4:l=m\ns=5\nreturn A.c(A.cN(),$async$$0)\ncase 5:l.b=b\ns=6\nreturn A.c(A.iN(),$async$$0)\ncase 6:p=b\nm.a=p\no.d=new A.lm(p,m.b)\ncase 3:return A.m(null,r)}})\nreturn A.n($async$$0,r)},\n$S:14}\nA.d5.prototype={\nae(){return\"ProtocolVersion.\"+this.b}}\nA.lo.prototype={\ndj(a){this.aC(new A.lr(a))},\neS(a){this.aC(new A.lq(a))},\ndi(a){this.aC(new A.lp(a))}}\nA.lr.prototype={\n$2(a,b){var s=b==null?B.A:b\nthis.a.postMessage(a,s)},\n$S:19}\nA.lq.prototype={\n$2(a,b){var s=b==null?B.A:b\nthis.a.postMessage(a,s)},\n$S:19}\nA.lp.prototype={\n$2(a,b){var s=b==null?B.A:b\nthis.a.postMessage(a,s)},\n$S:19}\nA.jb.prototype={}\nA.c5.prototype={\naC(a){var s=this\nA.dN(a,\"SharedWorkerCompatibilityResult\",A.d([s.e,s.f,s.r,s.c,s.d,A.pK(s.a),s.b.c],t.f),null)}}\nA.dm.prototype={\naC(a){A.dN(a,\"Error\",this.a,null)},\nj(a){return\"Error in worker: \"+this.a},\n$ia5:1}\nA.dc.prototype={\naC(a){var s,r,q=this,p={}\np.sqlite=q.a.j(0)\ns=q.b\np.port=s\np.storage=q.c.b\np.database=q.d\nr=q.e\np.initPort=r\np.migrations=q.r\np.new_serialization=q.w\np.v=q.f.c\ns=A.d([s],t.W)\nif(r!=null)s.push(r)\nA.dN(a,\"ServeDriftDatabase\",p,s)}}\nA.da.prototype={\naC(a){A.dN(a,\"RequestCompatibilityCheck\",this.a,null)}}\nA.e9.prototype={\naC(a){var s=this,r={}\nr.supportsNestedWorkers=s.e\nr.canAccessOpfs=s.f\nr.supportsIndexedDb=s.w\nr.supportsSharedArrayBuffers=s.r\nr.indexedDbExists=s.c\nr.opfsExists=s.d\nr.existing=A.pK(s.a)\nr.v=s.b.c\nA.dN(a,\"DedicatedWorkerCompatibilityResult\",r,null)}}\nA.eB.prototype={\naC(a){A.dN(a,\"StartFileSystemServer\",this.a,null)}}\nA.fR.prototype={\naC(a){var s=this.a\nA.dN(a,\"DeleteDatabase\",A.d([s.a.b,s.b],t.s),null)}}\nA.o_.prototype={\n$1(a){this.b.transaction.abort()\nthis.a.a=!1},\n$S:10}\nA.od.prototype={\n$1(a){return t.m.a(a[1])},\n$S:56}\nA.fU.prototype={\neT(a){var s=a.w\nthis.a.hg(a.d,new A.jI(this,a)).hv(A.uP(a.b,a.f.c>=1,s),!s)},\naY(a,b,c,d,e){return this.kj(a,b,c,d,e)},\nkj(a,b,c,d,a0){var s=0,r=A.o(t.x),q,p=this,o,n,m,l,k,j,i,h,g,f,e\nvar $async$aY=A.p(function(a1,a2){if(a1===1)return A.l(a2,r)\nwhile(true)switch(s){case 0:s=3\nreturn A.c(A.lw(d),$async$aY)\ncase 3:f=a2\ne=null\ncase 4:switch(a0.a){case 0:s=6\nbreak\ncase 1:s=7\nbreak\ncase 3:s=8\nbreak\ncase 2:s=9\nbreak\ncase 4:s=10\nbreak\ndefault:s=11\nbreak}break\ncase 6:s=12\nreturn A.c(A.hx(\"drift_db/\"+a),$async$aY)\ncase 12:o=a2\ne=o.gb9()\ns=5\nbreak\ncase 7:s=13\nreturn A.c(p.cw(a),$async$aY)\ncase 13:o=a2\ne=o.gb9()\ns=5\nbreak\ncase 8:case 9:s=14\nreturn A.c(A.h5(a),$async$aY)\ncase 14:o=a2\ne=o.gb9()\ns=5\nbreak\ncase 10:o=A.ow(null)\ns=5\nbreak\ncase 11:o=null\ncase 5:s=c!=null&&o.ck(\"/database\",0)===0?15:16\nbreak\ncase 15:n=c.$0()\ns=17\nreturn A.c(t.eY.b(n)?n:A.eX(n,t.aD),$async$aY)\ncase 17:m=a2\nif(m!=null){l=o.aZ(new A.ez(\"/database\"),4).a\nl.bH(m,0)\nl.cl()}case 16:n=f.a\nn=n.b\nk=n.c0(B.i.a5(o.a),1)\nj=n.c.e\ni=j.a\nj.q(0,i,o)\nh=A.h(A.r(n.y.call(null,k,i,1)))\nn=$.rP()\nn.a.set(o,h)\nn=A.uh(t.N,t.eT)\ng=new A.hT(new A.nH(f,\"/database\",null,p.b,!0,b,new A.ko(n)),!1,!0,new A.bh(),new A.bh())\nif(e!=null){q=A.tK(g,new A.m5(e,g))\ns=1\nbreak}else{q=g\ns=1\nbreak}case 1:return A.m(q,r)}})\nreturn A.n($async$aY,r)},\ncw(a){return this.iy(a)},\niy(a){var s=0,r=A.o(t.aT),q,p,o,n,m,l,k,j,i\nvar $async$cw=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:k=self\nj=new k.SharedArrayBuffer(8)\ni=k.Int32Array\ni=t.ha.a(A.dT(i,[j]))\nk.Atomics.store(i,0,-1)\ni={clientVersion:1,root:\"drift_db/\"+a,synchronizationBuffer:j,communicationBuffer:new k.SharedArrayBuffer(67584)}\np=new k.Worker(A.eF().j(0))\nnew A.eB(i).dj(p)\ns=3\nreturn A.c(new A.eU(p,\"message\",!1,t.fF).gG(0),$async$cw)\ncase 3:o=A.qb(i.synchronizationBuffer)\ni=i.communicationBuffer\nn=A.qe(i,65536,2048)\nk=k.Uint8Array\nk=t.Z.a(A.dT(k,[i]))\nm=A.jl(\"/\",$.cP())\nl=$.iP()\nq=new A.dl(o,new A.bi(i,n,k),m,l,\"dart-sqlite3-vfs\")\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$cw,r)}}\nA.jI.prototype={\n$0(){var s=this.b,r=s.e,q=r!=null?new A.jF(r):null,p=this.a,o=A.uC(new A.hc(new A.jG(p,s,q)),!1,!0),n=new A.k($.i,t.D),m=new A.db(s.c,o,new A.a8(n,t.F))\nn.ai(new A.jH(p,s,m))\nreturn m},\n$S:57}\nA.jF.prototype={\n$0(){var s=new A.k($.i,t.fX),r=this.a\nr.postMessage(!0)\nr.onmessage=A.bb(new A.jE(new A.a2(s,t.fu)))\nreturn s},\n$S:58}\nA.jE.prototype={\n$1(a){var s=t.dE.a(a.data),r=s==null?null:s\nthis.a.L(r)},\n$S:10}\nA.jG.prototype={\n$0(){var s=this.b\nreturn this.a.aY(s.d,s.r,this.c,s.a,s.c)},\n$S:59}\nA.jH.prototype={\n$0(){this.a.a.A(0,this.b.d)\nthis.c.b.hy()},\n$S:9}\nA.m5.prototype={\nc2(a){return this.jF(a)},\njF(a){var s=0,r=A.o(t.H),q=this,p\nvar $async$c2=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:s=2\nreturn A.c(a.p(),$async$c2)\ncase 2:s=q.b===a?3:4\nbreak\ncase 3:p=q.a.$0()\ns=5\nreturn A.c(p instanceof A.k?p:A.eX(p,t.H),$async$c2)\ncase 5:case 4:return A.m(null,r)}})\nreturn A.n($async$c2,r)}}\nA.db.prototype={\nhv(a,b){var s,r,q;++this.c\ns=t.X\ns=A.v9(new A.kA(this),s,s).gjD().$1(a.ghD())\nr=a.$ti\nq=new A.e5(r.h(\"e5<1>\"))\nq.b=new A.eO(q,a.ghz())\nq.a=new A.eP(s,q,r.h(\"eP<1>\"))\nthis.b.hw(q,b)}}\nA.kA.prototype={\n$1(a){var s=this.a\nif(--s.c===0)s.d.aV()\ns=a.a\nif((s.e&2)!==0)A.y(A.B(\"Stream is already closed\"))\ns.eW()},\n$S:60}\nA.lm.prototype={}\nA.jf.prototype={\n$1(a){this.a.L(this.c.a(this.b.result))},\n$S:1}\nA.jg.prototype={\n$1(a){var s=this.b.error\nif(s==null)s=a\nthis.a.aK(s)},\n$S:1}\nA.jh.prototype={\n$1(a){var s=this.b.error\nif(s==null)s=a\nthis.a.aK(s)},\n$S:1}\nA.kK.prototype={\nT(){A.aB(this.a,\"connect\",new A.kP(this),!1)},\ndV(a){return this.iB(a)},\niB(a){var s=0,r=A.o(t.H),q=this,p,o\nvar $async$dV=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:p=a.ports\no=J.aO(t.cl.b(p)?p:new A.ah(p,A.Q(p).h(\"ah<1,A>\")),0)\no.start()\nA.aB(o,\"message\",new A.kL(q,o),!1)\nreturn A.m(null,r)}})\nreturn A.n($async$dV,r)},\ncA(a,b){return this.iz(a,b)},\niz(a,b){var s=0,r=A.o(t.H),q=1,p,o=this,n,m,l,k,j,i,h,g\nvar $async$cA=A.p(function(c,d){if(c===1){p=d\ns=q}while(true)switch(s){case 0:q=3\nn=A.oL(t.m.a(b.data))\nm=n\nl=null\ni=m instanceof A.da\nif(i)l=m.a\ns=i?7:8\nbreak\ncase 7:s=9\nreturn A.c(o.bW(l),$async$cA)\ncase 9:k=d\nk.eS(a)\ns=6\nbreak\ncase 8:if(m instanceof A.dc&&B.w===m.c){o.c.eT(n)\ns=6\nbreak}if(m instanceof A.dc){i=o.b\ni.toString\nn.dj(i)\ns=6\nbreak}i=A.K(\"Unknown message\",null)\nthrow A.a(i)\ncase 6:q=1\ns=5\nbreak\ncase 3:q=2\ng=p\nj=A.E(g)\nnew A.dm(J.aU(j)).eS(a)\na.close()\ns=5\nbreak\ncase 2:s=1\nbreak\ncase 5:return A.m(null,r)\ncase 1:return A.l(p,r)}})\nreturn A.n($async$cA,r)},\nbW(a){return this.je(a)},\nje(a){var s=0,r=A.o(t.fM),q,p=this,o,n,m,l,k,j,i,h,g,f,e,d,c\nvar $async$bW=A.p(function(b,a0){if(b===1)return A.l(a0,r)\nwhile(true)switch(s){case 0:l={}\nk=t.m.a(self)\nj=\"Worker\" in k\ns=3\nreturn A.c(A.iN(),$async$bW)\ncase 3:i=a0\ns=!j?4:6\nbreak\ncase 4:l=p.c.a.i(0,a)\nif(l==null)o=null\nelse{l=l.a\nl=l===B.w||l===B.E\no=l}h=A\ng=!1\nf=!1\ne=i\nd=B.B\nc=B.v\ns=o==null?7:9\nbreak\ncase 7:s=10\nreturn A.c(A.dU(a),$async$bW)\ncase 10:s=8\nbreak\ncase 9:a0=o\ncase 8:q=new h.c5(g,f,e,d,c,a0,!1)\ns=1\nbreak\ns=5\nbreak\ncase 6:n=p.b\nif(n==null)n=p.b=new k.Worker(A.eF().j(0))\nnew A.da(a).dj(n)\nk=new A.k($.i,t.a9)\nl.a=l.b=null\nm=new A.kO(l,new A.a2(k,t.bi),i)\nl.b=A.aB(n,\"message\",new A.kM(m),!1)\nl.a=A.aB(n,\"error\",new A.kN(p,m,n),!1)\nq=k\ns=1\nbreak\ncase 5:case 1:return A.m(q,r)}})\nreturn A.n($async$bW,r)}}\nA.kP.prototype={\n$1(a){return this.a.dV(a)},\n$S:1}\nA.kL.prototype={\n$1(a){return this.a.cA(this.b,a)},\n$S:1}\nA.kO.prototype={\n$4(a,b,c,d){var s,r=this.b\nif((r.a.a&30)===0){r.L(new A.c5(!0,a,this.c,d,B.v,c,b))\nr=this.a\ns=r.b\nif(s!=null)s.J()\nr=r.a\nif(r!=null)r.J()}},\n$S:61}\nA.kM.prototype={\n$1(a){var s=t.ed.a(A.oL(t.m.a(a.data)))\nthis.a.$4(s.f,s.d,s.c,s.a)},\n$S:1}\nA.kN.prototype={\n$1(a){this.b.$4(!1,!1,!1,B.B)\nthis.c.terminate()\nthis.a.b=null},\n$S:1}\nA.c8.prototype={\nae(){return\"WasmStorageImplementation.\"+this.b}}\nA.bH.prototype={\nae(){return\"WebStorageApi.\"+this.b}}\nA.hT.prototype={}\nA.nH.prototype={\nkk(){var s=this.Q.ca(this.as)\nreturn s},\nbs(){var s=0,r=A.o(t.H),q\nvar $async$bs=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:q=A.eX(null,t.H)\ns=2\nreturn A.c(q,$async$bs)\ncase 2:return A.m(null,r)}})\nreturn A.n($async$bs,r)},\nbu(a,b){return this.j2(a,b)},\nj2(a,b){var s=0,r=A.o(t.z),q=this\nvar $async$bu=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:q.kD(a,b)\ns=!q.a?2:3\nbreak\ncase 2:s=4\nreturn A.c(q.bs(),$async$bu)\ncase 4:case 3:return A.m(null,r)}})\nreturn A.n($async$bu,r)},\na8(a,b){return this.ky(a,b)},\nky(a,b){var s=0,r=A.o(t.H),q=this\nvar $async$a8=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:s=2\nreturn A.c(q.bu(a,b),$async$a8)\ncase 2:return A.m(null,r)}})\nreturn A.n($async$a8,r)},\naw(a,b){return this.kz(a,b)},\nkz(a,b){var s=0,r=A.o(t.S),q,p=this,o,n\nvar $async$aw=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:s=3\nreturn A.c(p.bu(a,b),$async$aw)\ncase 3:o=p.b.b\nn=t.C.a(o.a.x2.call(null,o.b))\nq=A.h(self.Number(n))\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$aw,r)},\nd8(a,b){return this.kC(a,b)},\nkC(a,b){var s=0,r=A.o(t.S),q,p=this,o\nvar $async$d8=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:s=3\nreturn A.c(p.bu(a,b),$async$d8)\ncase 3:o=p.b.b\nq=A.h(A.r(o.a.x1.call(null,o.b)))\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$d8,r)},\nav(a){return this.kw(a)},\nkw(a){var s=0,r=A.o(t.H),q=this\nvar $async$av=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:q.kv(a)\ns=!q.a?2:3\nbreak\ncase 2:s=4\nreturn A.c(q.bs(),$async$av)\ncase 4:case 3:return A.m(null,r)}})\nreturn A.n($async$av,r)},\np(){var s=0,r=A.o(t.H),q=this\nvar $async$p=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:s=2\nreturn A.c(q.hH(),$async$p)\ncase 2:q.b.a7()\ns=3\nreturn A.c(q.bs(),$async$p)\ncase 3:return A.m(null,r)}})\nreturn A.n($async$p,r)}}\nA.fM.prototype={\nfS(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){var s\nA.rs(\"absolute\",A.d([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o],t.d4))\ns=this.a\ns=s.S(a)>0&&!s.ab(a)\nif(s)return a\ns=this.b\nreturn this.h8(0,s==null?A.pf():s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)},\naI(a){var s=null\nreturn this.fS(a,s,s,s,s,s,s,s,s,s,s,s,s,s,s)},\nh8(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q){var s=A.d([b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q],t.d4)\nA.rs(\"join\",s)\nreturn this.ke(new A.eI(s,t.eJ))},\nkd(a,b,c){var s=null\nreturn this.h8(0,b,c,s,s,s,s,s,s,s,s,s,s,s,s,s,s)},\nke(a){var s,r,q,p,o,n,m,l,k\nfor(s=a.gt(0),r=new A.eH(s,new A.jm()),q=this.a,p=!1,o=!1,n=\"\";r.k();){m=s.gm()\nif(q.ab(m)&&o){l=A.d4(m,q)\nk=n.charCodeAt(0)==0?n:n\nn=B.a.n(k,0,q.bE(k,!0))\nl.b=n\nif(q.c7(n))l.e[0]=q.gbk()\nn=\"\"+l.j(0)}else if(q.S(m)>0){o=!q.ab(m)\nn=\"\"+m}else{if(!(m.length!==0&&q.eh(m[0])))if(p)n+=q.gbk()\nn+=m}p=q.c7(m)}return n.charCodeAt(0)==0?n:n},\naQ(a,b){var s=A.d4(b,this.a),r=s.d,q=A.Q(r).h(\"aT<1>\")\nq=A.ay(new A.aT(r,new A.jn(),q),!0,q.h(\"f.E\"))\ns.d=q\nr=s.b\nif(r!=null)B.c.cY(q,0,r)\nreturn s.d},\nbA(a){var s\nif(!this.iA(a))return a\ns=A.d4(a,this.a)\ns.eE()\nreturn s.j(0)},\niA(a){var s,r,q,p,o,n,m,l,k=this.a,j=k.S(a)\nif(j!==0){if(k===$.fu())for(s=0;s<j;++s)if(a.charCodeAt(s)===47)return!0\nr=j\nq=47}else{r=0\nq=null}for(p=new A.e6(a).a,o=p.length,s=r,n=null;s<o;++s,n=q,q=m){m=p.charCodeAt(s)\nif(k.D(m)){if(k===$.fu()&&m===47)return!0\nif(q!=null&&k.D(q))return!0\nif(q===46)l=n==null||n===46||k.D(n)\nelse l=!1\nif(l)return!0}}if(q==null)return!0\nif(k.D(q))return!0\nif(q===46)k=n==null||k.D(n)||n===46\nelse k=!1\nif(k)return!0\nreturn!1},\neJ(a,b){var s,r,q,p,o=this,n='Unable to find a path to \"',m=b==null\nif(m&&o.a.S(a)<=0)return o.bA(a)\nif(m){m=o.b\nb=m==null?A.pf():m}else b=o.aI(b)\nm=o.a\nif(m.S(b)<=0&&m.S(a)>0)return o.bA(a)\nif(m.S(a)<=0||m.ab(a))a=o.aI(a)\nif(m.S(a)<=0&&m.S(b)>0)throw A.a(A.q1(n+a+'\" from \"'+b+'\".'))\ns=A.d4(b,m)\ns.eE()\nr=A.d4(a,m)\nr.eE()\nq=s.d\nif(q.length!==0&&J.X(q[0],\".\"))return r.j(0)\nq=s.b\np=r.b\nif(q!=p)q=q==null||p==null||!m.eG(q,p)\nelse q=!1\nif(q)return r.j(0)\nwhile(!0){q=s.d\nif(q.length!==0){p=r.d\nq=p.length!==0&&m.eG(q[0],p[0])}else q=!1\nif(!q)break\nB.c.d6(s.d,0)\nB.c.d6(s.e,1)\nB.c.d6(r.d,0)\nB.c.d6(r.e,1)}q=s.d\nif(q.length!==0&&J.X(q[0],\"..\"))throw A.a(A.q1(n+a+'\" from \"'+b+'\".'))\nq=t.N\nB.c.ev(r.d,0,A.b_(s.d.length,\"..\",!1,q))\np=r.e\np[0]=\"\"\nB.c.ev(p,1,A.b_(s.d.length,m.gbk(),!1,q))\nm=r.d\nq=m.length\nif(q===0)return\".\"\nif(q>1&&J.X(B.c.gC(m),\".\")){B.c.hi(r.d)\nm=r.e\nm.pop()\nm.pop()\nm.push(\"\")}r.b=\"\"\nr.hj()\nreturn r.j(0)},\nks(a){return this.eJ(a,null)},\niv(a,b){var s,r,q,p,o,n,m,l,k=this\na=a\nb=b\nr=k.a\nq=r.S(a)>0\np=r.S(b)>0\nif(q&&!p){b=k.aI(b)\nif(r.ab(a))a=k.aI(a)}else if(p&&!q){a=k.aI(a)\nif(r.ab(b))b=k.aI(b)}else if(p&&q){o=r.ab(b)\nn=r.ab(a)\nif(o&&!n)b=k.aI(b)\nelse if(n&&!o)a=k.aI(a)}m=k.iw(a,b)\nif(m!==B.n)return m\ns=null\ntry{s=k.eJ(b,a)}catch(l){if(A.E(l) instanceof A.eu)return B.k\nelse throw l}if(r.S(s)>0)return B.k\nif(J.X(s,\".\"))return B.W\nif(J.X(s,\"..\"))return B.k\nreturn J.ae(s)>=3&&J.tH(s,\"..\")&&r.D(J.tA(s,2))?B.k:B.X},\niw(a,b){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e=this\nif(a===\".\")a=\"\"\ns=e.a\nr=s.S(a)\nq=s.S(b)\nif(r!==q)return B.k\nfor(p=0;p<r;++p)if(!s.cR(a.charCodeAt(p),b.charCodeAt(p)))return B.k\no=b.length\nn=a.length\nm=q\nl=r\nk=47\nj=null\nwhile(!0){if(!(l<n&&m<o))break\nc$0:{i=a.charCodeAt(l)\nh=b.charCodeAt(m)\nif(s.cR(i,h)){if(s.D(i))j=l;++l;++m\nk=i\nbreak c$0}if(s.D(i)&&s.D(k)){g=l+1\nj=l\nl=g\nbreak c$0}else if(s.D(h)&&s.D(k)){++m\nbreak c$0}if(i===46&&s.D(k)){++l\nif(l===n)break\ni=a.charCodeAt(l)\nif(s.D(i)){g=l+1\nj=l\nl=g\nbreak c$0}if(i===46){++l\nif(l===n||s.D(a.charCodeAt(l)))return B.n}}if(h===46&&s.D(k)){++m\nif(m===o)break\nh=b.charCodeAt(m)\nif(s.D(h)){++m\nbreak c$0}if(h===46){++m\nif(m===o||s.D(b.charCodeAt(m)))return B.n}}if(e.cC(b,m)!==B.V)return B.n\nif(e.cC(a,l)!==B.V)return B.n\nreturn B.k}}if(m===o){if(l===n||s.D(a.charCodeAt(l)))j=l\nelse if(j==null)j=Math.max(0,r-1)\nf=e.cC(a,j)\nif(f===B.U)return B.W\nreturn f===B.T?B.n:B.k}f=e.cC(b,m)\nif(f===B.U)return B.W\nif(f===B.T)return B.n\nreturn s.D(b.charCodeAt(m))||s.D(k)?B.X:B.k},\ncC(a,b){var s,r,q,p,o,n,m\nfor(s=a.length,r=this.a,q=b,p=0,o=!1;q<s;){while(!0){if(!(q<s&&r.D(a.charCodeAt(q))))break;++q}if(q===s)break\nn=q\nwhile(!0){if(!(n<s&&!r.D(a.charCodeAt(n))))break;++n}m=n-q\nif(!(m===1&&a.charCodeAt(q)===46))if(m===2&&a.charCodeAt(q)===46&&a.charCodeAt(q+1)===46){--p\nif(p<0)break\nif(p===0)o=!0}else ++p\nif(n===s)break\nq=n+1}if(p<0)return B.T\nif(p===0)return B.U\nif(o)return B.bt\nreturn B.V},\nhp(a){var s,r=this.a\nif(r.S(a)<=0)return r.hh(a)\nelse{s=this.b\nreturn r.ec(this.kd(0,s==null?A.pf():s,a))}},\nko(a){var s,r,q=this,p=A.pa(a)\nif(p.gY()===\"file\"&&q.a===$.cP())return p.j(0)\nelse if(p.gY()!==\"file\"&&p.gY()!==\"\"&&q.a!==$.cP())return p.j(0)\ns=q.bA(q.a.d3(A.pa(p)))\nr=q.ks(s)\nreturn q.aQ(0,r).length>q.aQ(0,s).length?s:r}}\nA.jm.prototype={\n$1(a){return a!==\"\"},\n$S:2}\nA.jn.prototype={\n$1(a){return a.length!==0},\n$S:2}\nA.nY.prototype={\n$1(a){return a==null?\"null\":'\"'+a+'\"'},\n$S:63}\nA.dB.prototype={\nj(a){return this.a}}\nA.dC.prototype={\nj(a){return this.a}}\nA.k7.prototype={\nhu(a){var s=this.S(a)\nif(s>0)return B.a.n(a,0,s)\nreturn this.ab(a)?a[0]:null},\nhh(a){var s,r=null,q=a.length\nif(q===0)return A.aj(r,r,r,r)\ns=A.jl(r,this).aQ(0,a)\nif(this.D(a.charCodeAt(q-1)))B.c.v(s,\"\")\nreturn A.aj(r,r,s,r)},\ncR(a,b){return a===b},\neG(a,b){return a===b}}\nA.km.prototype={\ngeu(){var s=this.d\nif(s.length!==0)s=J.X(B.c.gC(s),\"\")||!J.X(B.c.gC(this.e),\"\")\nelse s=!1\nreturn s},\nhj(){var s,r,q=this\nwhile(!0){s=q.d\nif(!(s.length!==0&&J.X(B.c.gC(s),\"\")))break\nB.c.hi(q.d)\nq.e.pop()}s=q.e\nr=s.length\nif(r!==0)s[r-1]=\"\"},\neE(){var s,r,q,p,o,n,m=this,l=A.d([],t.s)\nfor(s=m.d,r=s.length,q=0,p=0;p<s.length;s.length===r||(0,A.W)(s),++p){o=s[p]\nn=J.cg(o)\nif(!(n.O(o,\".\")||n.O(o,\"\")))if(n.O(o,\"..\"))if(l.length!==0)l.pop()\nelse ++q\nelse l.push(o)}if(m.b==null)B.c.ev(l,0,A.b_(q,\"..\",!1,t.N))\nif(l.length===0&&m.b==null)l.push(\".\")\nm.d=l\ns=m.a\nm.e=A.b_(l.length+1,s.gbk(),!0,t.N)\nr=m.b\nif(r==null||l.length===0||!s.c7(r))m.e[0]=\"\"\nr=m.b\nif(r!=null&&s===$.fu()){r.toString\nm.b=A.bc(r,\"/\",\"\\\\\")}m.hj()},\nj(a){var s,r=this,q=r.b\nq=q!=null?\"\"+q:\"\"\nfor(s=0;s<r.d.length;++s)q=q+A.u(r.e[s])+A.u(r.d[s])\nq+=A.u(B.c.gC(r.e))\nreturn q.charCodeAt(0)==0?q:q}}\nA.eu.prototype={\nj(a){return\"PathException: \"+this.a},\n$ia5:1}\nA.l1.prototype={\nj(a){return this.geD()}}\nA.kn.prototype={\neh(a){return B.a.M(a,\"/\")},\nD(a){return a===47},\nc7(a){var s=a.length\nreturn s!==0&&a.charCodeAt(s-1)!==47},\nbE(a,b){if(a.length!==0&&a.charCodeAt(0)===47)return 1\nreturn 0},\nS(a){return this.bE(a,!1)},\nab(a){return!1},\nd3(a){var s\nif(a.gY()===\"\"||a.gY()===\"file\"){s=a.gac()\nreturn A.p4(s,0,s.length,B.j,!1)}throw A.a(A.K(\"Uri \"+a.j(0)+\" must have scheme 'file:'.\",null))},\nec(a){var s=A.d4(a,this),r=s.d\nif(r.length===0)B.c.aJ(r,A.d([\"\",\"\"],t.s))\nelse if(s.geu())B.c.v(s.d,\"\")\nreturn A.aj(null,null,s.d,\"file\")},\ngeD(){return\"posix\"},\ngbk(){return\"/\"}}\nA.lk.prototype={\neh(a){return B.a.M(a,\"/\")},\nD(a){return a===47},\nc7(a){var s=a.length\nif(s===0)return!1\nif(a.charCodeAt(s-1)!==47)return!0\nreturn B.a.ek(a,\"://\")&&this.S(a)===s},\nbE(a,b){var s,r,q,p=a.length\nif(p===0)return 0\nif(a.charCodeAt(0)===47)return 1\nfor(s=0;s<p;++s){r=a.charCodeAt(s)\nif(r===47)return 0\nif(r===58){if(s===0)return 0\nq=B.a.aW(a,\"/\",B.a.E(a,\"//\",s+1)?s+3:s)\nif(q<=0)return p\nif(!b||p<q+3)return q\nif(!B.a.u(a,\"file://\"))return q\np=A.rz(a,q+1)\nreturn p==null?q:p}}return 0},\nS(a){return this.bE(a,!1)},\nab(a){return a.length!==0&&a.charCodeAt(0)===47},\nd3(a){return a.j(0)},\nhh(a){return A.bm(a)},\nec(a){return A.bm(a)},\ngeD(){return\"url\"},\ngbk(){return\"/\"}}\nA.lM.prototype={\neh(a){return B.a.M(a,\"/\")},\nD(a){return a===47||a===92},\nc7(a){var s=a.length\nif(s===0)return!1\ns=a.charCodeAt(s-1)\nreturn!(s===47||s===92)},\nbE(a,b){var s,r=a.length\nif(r===0)return 0\nif(a.charCodeAt(0)===47)return 1\nif(a.charCodeAt(0)===92){if(r<2||a.charCodeAt(1)!==92)return 1\ns=B.a.aW(a,\"\\\\\",2)\nif(s>0){s=B.a.aW(a,\"\\\\\",s+1)\nif(s>0)return s}return r}if(r<3)return 0\nif(!A.rD(a.charCodeAt(0)))return 0\nif(a.charCodeAt(1)!==58)return 0\nr=a.charCodeAt(2)\nif(!(r===47||r===92))return 0\nreturn 3},\nS(a){return this.bE(a,!1)},\nab(a){return this.S(a)===1},\nd3(a){var s,r\nif(a.gY()!==\"\"&&a.gY()!==\"file\")throw A.a(A.K(\"Uri \"+a.j(0)+\" must have scheme 'file:'.\",null))\ns=a.gac()\nif(a.gbc()===\"\"){if(s.length>=3&&B.a.u(s,\"/\")&&A.rz(s,1)!=null)s=B.a.hl(s,\"/\",\"\")}else s=\"\\\\\\\\\"+a.gbc()+s\nr=A.bc(s,\"/\",\"\\\\\")\nreturn A.p4(r,0,r.length,B.j,!1)},\nec(a){var s,r,q=A.d4(a,this),p=q.b\np.toString\nif(B.a.u(p,\"\\\\\\\\\")){s=new A.aT(A.d(p.split(\"\\\\\"),t.s),new A.lN(),t.U)\nB.c.cY(q.d,0,s.gC(0))\nif(q.geu())B.c.v(q.d,\"\")\nreturn A.aj(s.gG(0),null,q.d,\"file\")}else{if(q.d.length===0||q.geu())B.c.v(q.d,\"\")\np=q.d\nr=q.b\nr.toString\nr=A.bc(r,\"/\",\"\")\nB.c.cY(p,0,A.bc(r,\"\\\\\",\"\"))\nreturn A.aj(null,null,q.d,\"file\")}},\ncR(a,b){var s\nif(a===b)return!0\nif(a===47)return b===92\nif(a===92)return b===47\nif((a^b)!==32)return!1\ns=a|32\nreturn s>=97&&s<=122},\neG(a,b){var s,r\nif(a===b)return!0\ns=a.length\nif(s!==b.length)return!1\nfor(r=0;r<s;++r)if(!this.cR(a.charCodeAt(r),b.charCodeAt(r)))return!1\nreturn!0},\ngeD(){return\"windows\"},\ngbk(){return\"\\\\\"}}\nA.lN.prototype={\n$1(a){return a!==\"\"},\n$S:2}\nA.hA.prototype={\nj(a){var s,r=this,q=r.d\nq=q==null?\"\":\"while \"+q+\", \"\nq=\"SqliteException(\"+r.c+\"): \"+q+r.a+\", \"+r.b\ns=r.e\nif(s!=null){q=q+\"\\n  Causing statement: \"+s\ns=r.f\nif(s!=null)q+=\", parameters: \"+new A.D(s,new A.kS(),A.Q(s).h(\"D<1,j>\")).aq(0,\", \")}return q.charCodeAt(0)==0?q:q},\n$ia5:1}\nA.kS.prototype={\n$1(a){if(t.p.b(a))return\"blob (\"+a.length+\" bytes)\"\nelse return J.aU(a)},\n$S:64}\nA.cj.prototype={}\nA.ku.prototype={}\nA.hB.prototype={}\nA.kv.prototype={}\nA.kx.prototype={}\nA.kw.prototype={}\nA.d8.prototype={}\nA.d9.prototype={}\nA.h_.prototype={\na7(){var s,r,q,p,o,n,m\nfor(s=this.d,r=s.length,q=0;q<s.length;s.length===r||(0,A.W)(s),++q){p=s[q]\nif(!p.d){p.d=!0\nif(!p.c){o=p.b\nA.h(A.r(o.c.id.call(null,o.b)))\np.c=!0}o=p.b\no.ba()\nA.h(A.r(o.c.to.call(null,o.b)))}}s=this.c\nn=A.h(A.r(s.a.ch.call(null,s.b)))\nm=n!==0?A.pe(this.b,s,n,\"closing database\",null,null):null\nif(m!=null)throw A.a(m)}}\nA.jr.prototype={\ngkG(){var s,r,q=this.kn(\"PRAGMA user_version;\")\ntry{s=q.eR(new A.cr(B.aR))\nr=A.h(J.fy(s).b[0])\nreturn r}finally{q.a7()}},\nfY(a,b,c,d,e){var s,r,q,p,o,n=null,m=this.b,l=B.i.a5(e)\nif(l.length>255)A.y(A.ag(e,\"functionName\",\"Must not exceed 255 bytes when utf-8 encoded\"))\ns=new Uint8Array(A.iJ(l))\nr=c?526337:2049\nq=m.a\np=q.c0(s,1)\nm=A.cM(q.w,\"call\",[null,m.b,p,a.a,r,q.c.kr(new A.ht(new A.jt(d),n,n))])\no=A.h(m)\nq.e.call(null,p)\nif(o!==0)A.iO(this,o,n,n,n)},\na6(a,b,c,d){return this.fY(a,b,!0,c,d)},\na7(){var s,r,q,p=this\nif(p.e)return\n$.dY().h_(p)\np.e=!0\nfor(s=p.d,r=0;!1;++r)s[r].p()\ns=p.b\nq=s.a\nq.c.r=null\nq.Q.call(null,s.b,-1)\np.c.a7()},\nh1(a){var s,r,q,p,o=this,n=B.t\nif(J.ae(n)===0){if(o.e)A.y(A.B(\"This database has already been closed\"))\nr=o.b\nq=r.a\ns=q.c0(B.i.a5(a),1)\np=A.h(A.cM(q.dx,\"call\",[null,r.b,s,0,0,0]))\nq.e.call(null,s)\nif(p!==0)A.iO(o,p,\"executing\",a,n)}else{s=o.d4(a,!0)\ntry{s.h2(new A.cr(n))}finally{s.a7()}}},\niN(a,b,c,a0,a1){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d=this\nif(d.e)A.y(A.B(\"This database has already been closed\"))\ns=B.i.a5(a)\nr=d.b\nq=r.a\np=q.bw(s)\no=q.d\nn=A.h(A.r(o.call(null,4)))\no=A.h(A.r(o.call(null,4)))\nm=new A.lz(r,p,n,o)\nl=A.d([],t.bb)\nk=new A.js(m,l)\nfor(r=s.length,q=q.b,j=0;j<r;j=g){i=m.eU(j,r-j,0)\nn=i.a\nif(n!==0){k.$0()\nA.iO(d,n,\"preparing statement\",a,null)}n=q.buffer\nh=B.b.I(n.byteLength,4)\ng=new Int32Array(n,0,h)[B.b.P(o,2)]-p\nf=i.b\nif(f!=null)l.push(new A.df(f,d,new A.cX(f),new A.fm(!1).dD(s,j,g,!0)))\nif(l.length===c){j=g\nbreak}}if(b)for(;j<r;){i=m.eU(j,r-j,0)\nn=q.buffer\nh=B.b.I(n.byteLength,4)\nj=new Int32Array(n,0,h)[B.b.P(o,2)]-p\nf=i.b\nif(f!=null){l.push(new A.df(f,d,new A.cX(f),\"\"))\nk.$0()\nthrow A.a(A.ag(a,\"sql\",\"Had an unexpected trailing statement.\"))}else if(i.a!==0){k.$0()\nthrow A.a(A.ag(a,\"sql\",\"Has trailing data after the first sql statement:\"))}}m.p()\nfor(r=l.length,q=d.c.d,e=0;e<l.length;l.length===r||(0,A.W)(l),++e)q.push(l[e].c)\nreturn l},\nd4(a,b){var s=this.iN(a,b,1,!1,!0)\nif(s.length===0)throw A.a(A.ag(a,\"sql\",\"Must contain an SQL statement.\"))\nreturn B.c.gG(s)},\nkn(a){return this.d4(a,!1)}}\nA.jt.prototype={\n$2(a,b){A.vQ(a,this.a,b)},\n$S:65}\nA.js.prototype={\n$0(){var s,r,q,p,o,n\nthis.a.p()\nfor(s=this.b,r=s.length,q=0;q<s.length;s.length===r||(0,A.W)(s),++q){p=s[q]\no=p.c\nif(!o.d){n=$.dY().a\nif(n!=null)n.unregister(p)\nif(!o.d){o.d=!0\nif(!o.c){n=o.b\nA.h(A.r(n.c.id.call(null,n.b)))\no.c=!0}n=o.b\nn.ba()\nA.h(A.r(n.c.to.call(null,n.b)))}n=p.b\nif(!n.e)B.c.A(n.c.d,o)}}},\n$S:0}\nA.hQ.prototype={\ngl(a){return this.a.b},\ni(a,b){var s,r,q,p=this.a,o=p.b\nif(0>b||b>=o)A.y(A.h4(b,o,this,null,\"index\"))\ns=this.b[b]\nr=p.i(0,b)\np=r.a\nq=r.b\nswitch(A.h(A.r(p.jU.call(null,q)))){case 1:q=t.C.a(p.jV.call(null,q))\nreturn A.h(self.Number(q))\ncase 2:return A.r(p.jW.call(null,q))\ncase 3:o=A.h(A.r(p.h3.call(null,q)))\nreturn A.c9(p.b,A.h(A.r(p.jX.call(null,q))),o)\ncase 4:o=A.h(A.r(p.h3.call(null,q)))\nreturn A.qv(p.b,A.h(A.r(p.jY.call(null,q))),o)\ncase 5:default:return null}},\nq(a,b,c){throw A.a(A.K(\"The argument list is unmodifiable\",null))}}\nA.br.prototype={}\nA.o4.prototype={\n$1(a){a.a7()},\n$S:66}\nA.kR.prototype={\nca(a){var s,r,q,p,o,n,m,l,k\nswitch(2){case 2:break}s=this.a\nr=s.b\nq=r.c0(B.i.a5(a),1)\np=A.h(A.r(r.d.call(null,4)))\no=A.h(A.r(A.cM(r.ay,\"call\",[null,q,p,6,0])))\nn=A.ct(r.b.buffer,0,null)[B.b.P(p,2)]\nm=r.e\nm.call(null,q)\nm.call(null,0)\nm=new A.ln(r,n)\nif(o!==0){l=A.pe(s,m,o,\"opening the database\",null,null)\nA.h(A.r(r.ch.call(null,n)))\nthrow A.a(l)}A.h(A.r(r.db.call(null,n,1)))\nr=A.d([],t.eC)\nk=new A.h_(s,m,A.d([],t.eV))\nr=new A.jr(s,m,k,r)\ns=$.dY().a\nif(s!=null)s.register(r,k,r)\nreturn r}}\nA.cX.prototype={\na7(){var s,r=this\nif(!r.d){r.d=!0\nr.bR()\ns=r.b\ns.ba()\nA.h(A.r(s.c.to.call(null,s.b)))}},\nbR(){if(!this.c){var s=this.b\nA.h(A.r(s.c.id.call(null,s.b)))\nthis.c=!0}}}\nA.df.prototype={\ngi0(){var s,r,q,p,o,n=this.a,m=n.c,l=n.b,k=A.h(A.r(m.fy.call(null,l)))\nn=A.d([],t.s)\nfor(s=m.go,m=m.b,r=0;r<k;++r){q=A.h(A.r(s.call(null,l,r)))\np=m.buffer\no=A.oN(m,q)\np=new Uint8Array(p,q,o)\nn.push(new A.fm(!1).dD(p,0,null,!0))}return n},\ngjg(){return null},\nbR(){var s=this.c\ns.bR()\ns.b.ba()},\nff(){var s,r=this,q=r.c.c=!1,p=r.a,o=p.b\np=p.c.k1\ndo s=A.h(A.r(p.call(null,o)))\nwhile(s===100)\nif(s!==0?s!==101:q)A.iO(r.b,s,\"executing statement\",r.d,r.e)},\nj3(){var s,r,q,p,o,n,m,l,k=this,j=A.d([],t.gz),i=k.c.c=!1\nfor(s=k.a,r=s.c,q=s.b,s=r.k1,r=r.fy,p=-1;o=A.h(A.r(s.call(null,q))),o===100;){if(p===-1)p=A.h(A.r(r.call(null,q)))\nn=[]\nfor(m=0;m<p;++m)n.push(k.iQ(m))\nj.push(n)}if(o!==0?o!==101:i)A.iO(k.b,o,\"selecting from statement\",k.d,k.e)\nl=k.gi0()\nk.gjg()\ni=new A.hu(j,l,B.aU)\ni.hY()\nreturn i},\niQ(a){var s,r=this.a,q=r.c,p=r.b\nswitch(A.h(A.r(q.k2.call(null,p,a)))){case 1:p=t.C.a(q.k3.call(null,p,a))\nreturn-9007199254740992<=p&&p<=9007199254740992?A.h(self.Number(p)):A.oU(p.toString(),null)\ncase 2:return A.r(q.k4.call(null,p,a))\ncase 3:return A.c9(q.b,A.h(A.r(q.p1.call(null,p,a))),null)\ncase 4:s=A.h(A.r(q.ok.call(null,p,a)))\nreturn A.qv(q.b,A.h(A.r(q.p2.call(null,p,a))),s)\ncase 5:default:return null}},\nhW(a){var s,r=a.length,q=this.a,p=A.h(A.r(q.c.fx.call(null,q.b)))\nif(r!==p)A.y(A.ag(a,\"parameters\",\"Expected \"+p+\" parameters, got \"+r))\nq=a.length\nif(q===0)return\nfor(s=1;s<=a.length;++s)this.hX(a[s-1],s)\nthis.e=a},\nhX(a,b){var s,r,q,p,o,n=this\n$label0$0:{s=null\nif(a==null){r=n.a\nA.h(A.r(r.c.p3.call(null,r.b,b)))\nbreak $label0$0}if(A.bn(a)){r=n.a\nA.h(A.r(r.c.p4.call(null,r.b,b,self.BigInt(a))))\nbreak $label0$0}if(a instanceof A.a6){r=n.a\nn=A.pB(a).j(0)\nA.h(A.r(r.c.p4.call(null,r.b,b,self.BigInt(n))))\nbreak $label0$0}if(A.bM(a)){r=n.a\nn=a?1:0\nA.h(A.r(r.c.p4.call(null,r.b,b,self.BigInt(n))))\nbreak $label0$0}if(typeof a==\"number\"){r=n.a\nA.h(A.r(r.c.R8.call(null,r.b,b,a)))\nbreak $label0$0}if(typeof a==\"string\"){r=n.a\nq=B.i.a5(a)\np=r.c\no=p.bw(q)\nr.d.push(o)\nA.h(A.cM(p.RG,\"call\",[null,r.b,b,o,q.length,0]))\nbreak $label0$0}if(t.I.b(a)){r=n.a\np=r.c\no=p.bw(a)\nr.d.push(o)\nn=J.ae(a)\nA.h(A.cM(p.rx,\"call\",[null,r.b,b,o,self.BigInt(n),0]))\nbreak $label0$0}s=A.y(A.ag(a,\"params[\"+b+\"]\",\"Allowed parameters must either be null or bool, int, num, String or List<int>.\"))}return s},\ndt(a){$label0$0:{this.hW(a.a)\nbreak $label0$0}},\na7(){var s,r=this.c\nif(!r.d){$.dY().h_(this)\nr.a7()\ns=this.b\nif(!s.e)B.c.A(s.c.d,r)}},\neR(a){var s=this\nif(s.c.d)A.y(A.B(u.D))\ns.bR()\ns.dt(a)\nreturn s.j3()},\nh2(a){var s=this\nif(s.c.d)A.y(A.B(u.D))\ns.bR()\ns.dt(a)\ns.ff()}}\nA.jo.prototype={\nhY(){var s,r,q,p,o=A.a3(t.N,t.S)\nfor(s=this.a,r=s.length,q=0;q<s.length;s.length===r||(0,A.W)(s),++q){p=s[q]\no.q(0,p,B.c.d0(s,p))}this.c=o}}\nA.hu.prototype={\ngt(a){return new A.nh(this)},\ni(a,b){return new A.bk(this,A.aG(this.d[b],t.X))},\nq(a,b,c){throw A.a(A.H(\"Can't change rows from a result set\"))},\ngl(a){return this.d.length},\n$iv:1,\n$if:1,\n$iq:1}\nA.bk.prototype={\ni(a,b){var s\nif(typeof b!=\"string\"){if(A.bn(b))return this.b[b]\nreturn null}s=this.a.c.i(0,b)\nif(s==null)return null\nreturn this.b[s]},\nga_(){return this.a.a},\ngaP(){return this.b},\n$iaa:1}\nA.nh.prototype={\ngm(){var s=this.a\nreturn new A.bk(s,A.aG(s.d[this.b],t.X))},\nk(){return++this.b<this.a.d.length}}\nA.iu.prototype={}\nA.iv.prototype={}\nA.ix.prototype={}\nA.iy.prototype={}\nA.kl.prototype={\nae(){return\"OpenMode.\"+this.b}}\nA.cT.prototype={}\nA.cr.prototype={}\nA.aI.prototype={\nj(a){return\"VfsException(\"+this.a+\")\"},\n$ia5:1}\nA.ez.prototype={}\nA.bF.prototype={}\nA.fI.prototype={\nkH(a){var s,r,q\nfor(s=a.length,r=this.b,q=0;q<s;++q)a[q]=r.hc(256)}}\nA.fH.prototype={\ngeP(){return 0},\neQ(a,b){var s=this.eI(a,b),r=a.length\nif(s<r){B.e.en(a,s,r,0)\nthrow A.a(B.bq)}},\n$idj:1}\nA.lx.prototype={}\nA.ln.prototype={}\nA.lz.prototype={\np(){var s=this,r=s.a.a.e\nr.call(null,s.b)\nr.call(null,s.c)\nr.call(null,s.d)},\neU(a,b,c){var s=this,r=s.a,q=r.a,p=s.c,o=A.h(A.cM(q.fr,\"call\",[null,r.b,s.b+a,b,c,p,s.d])),n=A.ct(q.b.buffer,0,null)[B.b.P(p,2)]\nreturn new A.hB(o,n===0?null:new A.ly(n,q,A.d([],t.t)))}}\nA.ly.prototype={\nba(){var s,r,q,p\nfor(s=this.d,r=s.length,q=this.c.e,p=0;p<s.length;s.length===r||(0,A.W)(s),++p)q.call(null,s[p])\nB.c.c1(s)}}\nA.c7.prototype={}\nA.bG.prototype={}\nA.dk.prototype={\ni(a,b){var s=this.a\nreturn new A.bG(s,A.ct(s.b.buffer,0,null)[B.b.P(this.c+b*4,2)])},\nq(a,b,c){throw A.a(A.H(\"Setting element in WasmValueList\"))},\ngl(a){return this.b}}\nA.e0.prototype={\nR(a,b,c,d){var s,r=null,q={},p=t.m.a(A.ha(this.a,self.Symbol.asyncIterator,r,r,r,r)),o=A.eD(r,r,!0,this.$ti.c)\nq.a=null\ns=new A.iW(q,this,p,o)\no.d=s\no.f=new A.iX(q,o,s)\nreturn new A.an(o,A.t(o).h(\"an<1>\")).R(a,b,c,d)},\naX(a,b,c){return this.R(a,null,b,c)}}\nA.iW.prototype={\n$0(){var s,r=this,q=r.c.next(),p=r.a\np.a=q\ns=r.d\nA.a_(q,t.m).bG(new A.iY(p,r.b,s,r),s.gfT(),t.P)},\n$S:0}\nA.iY.prototype={\n$1(a){var s,r,q=this,p=a.done\nif(p==null)p=null\ns=a.value\nr=q.c\nif(p===!0){r.p()\nq.a.a=null}else{r.v(0,s==null?q.b.$ti.c.a(s):s)\nq.a.a=null\np=r.b\nif(!((p&1)!==0?(r.gaT().e&4)!==0:(p&2)===0))q.d.$0()}},\n$S:10}\nA.iX.prototype={\n$0(){var s,r\nif(this.a.a==null){s=this.b\nr=s.b\ns=!((r&1)!==0?(s.gaT().e&4)!==0:(r&2)===0)}else s=!1\nif(s)this.c.$0()},\n$S:0}\nA.cD.prototype={\nJ(){var s=0,r=A.o(t.H),q=this,p\nvar $async$J=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:p=q.b\nif(p!=null)p.J()\np=q.c\nif(p!=null)p.J()\nq.c=q.b=null\nreturn A.m(null,r)}})\nreturn A.n($async$J,r)},\ngm(){var s=this.a\nreturn s==null?A.y(A.B(\"Await moveNext() first\")):s},\nk(){var s,r,q=this,p=q.a\nif(p!=null)p.continue()\np=new A.k($.i,t.k)\ns=new A.a8(p,t.fa)\nr=q.d\nq.b=A.aB(r,\"success\",new A.m6(q,s),!1)\nq.c=A.aB(r,\"error\",new A.m7(q,s),!1)\nreturn p}}\nA.m6.prototype={\n$1(a){var s,r=this.a\nr.J()\ns=r.$ti.h(\"1?\").a(r.d.result)\nr.a=s\nthis.b.L(s!=null)},\n$S:1}\nA.m7.prototype={\n$1(a){var s=this.a\ns.J()\ns=s.d.error\nif(s==null)s=a\nthis.b.aK(s)},\n$S:1}\nA.jd.prototype={\n$1(a){this.a.L(this.c.a(this.b.result))},\n$S:1}\nA.je.prototype={\n$1(a){var s=this.b.error\nif(s==null)s=a\nthis.a.aK(s)},\n$S:1}\nA.ji.prototype={\n$1(a){this.a.L(this.c.a(this.b.result))},\n$S:1}\nA.jj.prototype={\n$1(a){var s=this.b.error\nif(s==null)s=a\nthis.a.aK(s)},\n$S:1}\nA.jk.prototype={\n$1(a){var s=this.b.error\nif(s==null)s=a\nthis.a.aK(s)},\n$S:1}\nA.hV.prototype={\nhO(a){var s,r,q,p,o,n,m=self,l=m.Object.keys(a.exports)\nl=B.c.gt(l)\ns=this.b\nr=t.m\nq=this.a\np=t.g\nfor(;l.k();){o=A.ad(l.gm())\nn=a.exports[o]\nif(typeof n===\"function\")q.q(0,o,p.a(n))\nelse if(n instanceof m.WebAssembly.Global)s.q(0,o,r.a(n))}}}\nA.lu.prototype={\n$2(a,b){var s={}\nthis.a[a]=s\nb.aa(0,new A.lt(s))},\n$S:67}\nA.lt.prototype={\n$2(a,b){this.a[a]=b},\n$S:68}\nA.hW.prototype={}\nA.dl.prototype={\nj_(a,b){var s,r,q=this.e\nq.hq(b)\ns=this.d.b\nr=self\nr.Atomics.store(s,1,-1)\nr.Atomics.store(s,0,a.a)\nA.tL(s,0)\nr.Atomics.wait(s,1,-1)\ns=r.Atomics.load(s,1)\nif(s!==0)throw A.a(A.cz(s))\nreturn a.d.$1(q)},\na2(a,b){var s=t.cb\nreturn this.j_(a,b,s,s)},\nck(a,b){return this.a2(B.H,new A.aQ(a,b,0,0)).a},\nda(a,b){this.a2(B.G,new A.aQ(a,b,0,0))},\ndc(a){var s=this.r.aI(a)\nif($.iQ().iv(\"/\",s)!==B.X)throw A.a(B.ai)\nreturn s},\naZ(a,b){var s=a.a,r=this.a2(B.S,new A.aQ(s==null?A.ov(this.b,\"/\"):s,b,0,0))\nreturn new A.cH(new A.hU(this,r.b),r.a)},\nde(a){this.a2(B.M,new A.S(B.b.I(a.a,1000),0,0))},\np(){this.a2(B.I,B.h)}}\nA.hU.prototype={\ngeP(){return 2048},\neI(a,b){var s,r,q,p,o,n,m,l,k,j=a.length\nfor(s=this.a,r=this.b,q=s.e.a,p=t.Z,o=0;j>0;){n=Math.min(65536,j)\nj-=n\nm=s.a2(B.Q,new A.S(r,b+o,n)).a\nl=self.Uint8Array\nk=[q]\nk.push(0)\nk.push(m)\nA.ha(a,\"set\",p.a(A.dT(l,k)),o,null,null)\no+=m\nif(m<n)break}return o},\nd9(){return this.c!==0?1:0},\ncl(){this.a.a2(B.N,new A.S(this.b,0,0))},\ncm(){return this.a.a2(B.R,new A.S(this.b,0,0)).a},\ndd(a){var s=this\nif(s.c===0)s.a.a2(B.J,new A.S(s.b,a,0))\ns.c=a},\ndf(a){this.a.a2(B.O,new A.S(this.b,0,0))},\ncn(a){this.a.a2(B.P,new A.S(this.b,a,0))},\ndg(a){if(this.c!==0&&a===0)this.a.a2(B.K,new A.S(this.b,a,0))},\nbH(a,b){var s,r,q,p,o,n,m,l,k=a.length\nfor(s=this.a,r=s.e.c,q=this.b,p=0;k>0;){o=Math.min(65536,k)\nif(o===k)n=a\nelse{m=a.buffer\nl=a.byteOffset\nn=new Uint8Array(m,l,o)}A.ha(r,\"set\",n,0,null,null)\ns.a2(B.L,new A.S(q,b+p,o))\np+=o\nk-=o}}}\nA.kz.prototype={}\nA.bi.prototype={\nhq(a){var s,r\nif(!(a instanceof A.aW))if(a instanceof A.S){s=this.b\ns.setInt32(0,a.a,!1)\ns.setInt32(4,a.b,!1)\ns.setInt32(8,a.c,!1)\nif(a instanceof A.aQ){r=B.i.a5(a.d)\ns.setInt32(12,r.length,!1)\nB.e.aD(this.c,16,r)}}else throw A.a(A.H(\"Message \"+a.j(0)))}}\nA.ac.prototype={\nae(){return\"WorkerOperation.\"+this.b},\nkq(a){return this.c.$1(a)}}\nA.bw.prototype={}\nA.aW.prototype={}\nA.S.prototype={}\nA.aQ.prototype={}\nA.it.prototype={}\nA.eG.prototype={\nbS(a,b){return this.iX(a,b)},\nfD(a){return this.bS(a,!1)},\niX(a,b){var s=0,r=A.o(t.eg),q,p=this,o,n,m,l,k,j,i,h,g\nvar $async$bS=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:j=$.fw()\ni=j.eJ(a,\"/\")\nh=j.aQ(0,i)\ng=h.length\nj=g>=1\no=null\nif(j){n=g-1\nm=B.c.a0(h,0,n)\no=h[n]}else m=null\nif(!j)throw A.a(A.B(\"Pattern matching error\"))\nl=p.c\nj=m.length,n=t.m,k=0\ncase 3:if(!(k<m.length)){s=5\nbreak}s=6\nreturn A.c(A.a_(l.getDirectoryHandle(m[k],{create:b}),n),$async$bS)\ncase 6:l=d\ncase 4:m.length===j||(0,A.W)(m),++k\ns=3\nbreak\ncase 5:q=new A.it(i,l,o)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$bS,r)},\nbY(a){return this.jn(a)},\njn(a){var s=0,r=A.o(t.G),q,p=2,o,n=this,m,l,k,j\nvar $async$bY=A.p(function(b,c){if(b===1){o=c\ns=p}while(true)switch(s){case 0:p=4\ns=7\nreturn A.c(n.fD(a.d),$async$bY)\ncase 7:m=c\nl=m\ns=8\nreturn A.c(A.a_(l.b.getFileHandle(l.c,{create:!1}),t.m),$async$bY)\ncase 8:q=new A.S(1,0,0)\ns=1\nbreak\np=2\ns=6\nbreak\ncase 4:p=3\nj=o\nq=new A.S(0,0,0)\ns=1\nbreak\ns=6\nbreak\ncase 3:s=2\nbreak\ncase 6:case 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$bY,r)},\nbZ(a){return this.jp(a)},\njp(a){var s=0,r=A.o(t.H),q=1,p,o=this,n,m,l,k\nvar $async$bZ=A.p(function(b,c){if(b===1){p=c\ns=q}while(true)switch(s){case 0:s=2\nreturn A.c(o.fD(a.d),$async$bZ)\ncase 2:l=c\nq=4\ns=7\nreturn A.c(A.pN(l.b,l.c),$async$bZ)\ncase 7:q=1\ns=6\nbreak\ncase 4:q=3\nk=p\nn=A.E(k)\nA.u(n)\nthrow A.a(B.bo)\ns=6\nbreak\ncase 3:s=1\nbreak\ncase 6:return A.m(null,r)\ncase 1:return A.l(p,r)}})\nreturn A.n($async$bZ,r)},\nc_(a){return this.js(a)},\njs(a){var s=0,r=A.o(t.G),q,p=2,o,n=this,m,l,k,j,i,h,g,f,e\nvar $async$c_=A.p(function(b,c){if(b===1){o=c\ns=p}while(true)switch(s){case 0:h=a.a\ng=(h&4)!==0\nf=null\np=4\ns=7\nreturn A.c(n.bS(a.d,g),$async$c_)\ncase 7:f=c\np=2\ns=6\nbreak\ncase 4:p=3\ne=o\nl=A.cz(12)\nthrow A.a(l)\ns=6\nbreak\ncase 3:s=2\nbreak\ncase 6:l=f\ns=8\nreturn A.c(A.a_(l.b.getFileHandle(l.c,{create:g}),t.m),$async$c_)\ncase 8:k=c\nj=!g&&(h&1)!==0\nl=n.d++\ni=f.b\nn.f.q(0,l,new A.dA(l,j,(h&8)!==0,f.a,i,f.c,k))\nq=new A.S(j?1:0,l,0)\ns=1\nbreak\ncase 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$c_,r)},\ncJ(a){return this.jt(a)},\njt(a){var s=0,r=A.o(t.G),q,p=this,o,n,m\nvar $async$cJ=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:o=p.f.i(0,a.a)\no.toString\nn=A\nm=A\ns=3\nreturn A.c(p.aS(o),$async$cJ)\ncase 3:q=new n.S(m.jM(c,A.oF(p.b.a,0,a.c),{at:a.b}),0,0)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$cJ,r)},\ncL(a){return this.jx(a)},\njx(a){var s=0,r=A.o(t.q),q,p=this,o,n,m\nvar $async$cL=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:n=p.f.i(0,a.a)\nn.toString\no=a.c\nm=A\ns=3\nreturn A.c(p.aS(n),$async$cL)\ncase 3:if(m.ot(c,A.oF(p.b.a,0,o),{at:a.b})!==o)throw A.a(B.aj)\nq=B.h\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$cL,r)},\ncG(a){return this.jo(a)},\njo(a){var s=0,r=A.o(t.H),q=this,p\nvar $async$cG=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:p=q.f.A(0,a.a)\nq.r.A(0,p)\nif(p==null)throw A.a(B.bn)\nq.dz(p)\ns=p.c?2:3\nbreak\ncase 2:s=4\nreturn A.c(A.pN(p.e,p.f),$async$cG)\ncase 4:case 3:return A.m(null,r)}})\nreturn A.n($async$cG,r)},\ncH(a){return this.jq(a)},\njq(a){var s=0,r=A.o(t.G),q,p=2,o,n=[],m=this,l,k,j,i\nvar $async$cH=A.p(function(b,c){if(b===1){o=c\ns=p}while(true)switch(s){case 0:i=m.f.i(0,a.a)\ni.toString\nl=i\np=3\ns=6\nreturn A.c(m.aS(l),$async$cH)\ncase 6:k=c\nj=k.getSize()\nq=new A.S(j,0,0)\nn=[1]\ns=4\nbreak\nn.push(5)\ns=4\nbreak\ncase 3:n=[2]\ncase 4:p=2\ni=l\nif(m.r.A(0,i))m.dA(i)\ns=n.pop()\nbreak\ncase 5:case 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$cH,r)},\ncK(a){return this.jv(a)},\njv(a){var s=0,r=A.o(t.q),q,p=2,o,n=[],m=this,l,k,j\nvar $async$cK=A.p(function(b,c){if(b===1){o=c\ns=p}while(true)switch(s){case 0:j=m.f.i(0,a.a)\nj.toString\nl=j\nif(l.b)A.y(B.br)\np=3\ns=6\nreturn A.c(m.aS(l),$async$cK)\ncase 6:k=c\nk.truncate(a.b)\nn.push(5)\ns=4\nbreak\ncase 3:n=[2]\ncase 4:p=2\nj=l\nif(m.r.A(0,j))m.dA(j)\ns=n.pop()\nbreak\ncase 5:q=B.h\ns=1\nbreak\ncase 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$cK,r)},\nea(a){return this.ju(a)},\nju(a){var s=0,r=A.o(t.q),q,p=this,o,n\nvar $async$ea=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:o=p.f.i(0,a.a)\nn=o.x\nif(!o.b&&n!=null)n.flush()\nq=B.h\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$ea,r)},\ncI(a){return this.jr(a)},\njr(a){var s=0,r=A.o(t.q),q,p=2,o,n=this,m,l,k,j\nvar $async$cI=A.p(function(b,c){if(b===1){o=c\ns=p}while(true)switch(s){case 0:k=n.f.i(0,a.a)\nk.toString\nm=k\ns=m.x==null?3:5\nbreak\ncase 3:p=7\ns=10\nreturn A.c(n.aS(m),$async$cI)\ncase 10:m.w=!0\np=2\ns=9\nbreak\ncase 7:p=6\nj=o\nthrow A.a(B.bp)\ns=9\nbreak\ncase 6:s=2\nbreak\ncase 9:s=4\nbreak\ncase 5:m.w=!0\ncase 4:q=B.h\ns=1\nbreak\ncase 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$cI,r)},\neb(a){return this.jw(a)},\njw(a){var s=0,r=A.o(t.q),q,p=this,o\nvar $async$eb=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:o=p.f.i(0,a.a)\nif(o.x!=null&&a.b===0)p.dz(o)\nq=B.h\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$eb,r)},\nT(){var s=0,r=A.o(t.H),q=1,p,o=this,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1,a2,a3\nvar $async$T=A.p(function(a4,a5){if(a4===1){p=a5\ns=q}while(true)switch(s){case 0:h=o.a.b,g=o.b,f=o.r,e=f.$ti.c,d=o.giR(),c=t.G,b=t.eN,a=t.H\ncase 2:if(!!o.e){s=3\nbreak}a0=self\nif(a0.Atomics.wait(h,0,-1,150)===\"timed-out\"){B.c.aa(A.ay(f,!0,e),d)\ns=2\nbreak}n=null\nm=null\nl=null\nq=5\na1=a0.Atomics.load(h,0)\na0.Atomics.store(h,0,-1)\nm=B.aP[a1]\nl=m.kq(g)\nk=null\ncase 8:switch(m){case B.M:s=10\nbreak\ncase B.H:s=11\nbreak\ncase B.G:s=12\nbreak\ncase B.S:s=13\nbreak\ncase B.Q:s=14\nbreak\ncase B.L:s=15\nbreak\ncase B.N:s=16\nbreak\ncase B.R:s=17\nbreak\ncase B.P:s=18\nbreak\ncase B.O:s=19\nbreak\ncase B.J:s=20\nbreak\ncase B.K:s=21\nbreak\ncase B.I:s=22\nbreak\ndefault:s=9\nbreak}break\ncase 10:B.c.aa(A.ay(f,!0,e),d)\ns=23\nreturn A.c(A.pP(A.pJ(0,c.a(l).a),a),$async$T)\ncase 23:k=B.h\ns=9\nbreak\ncase 11:s=24\nreturn A.c(o.bY(b.a(l)),$async$T)\ncase 24:k=a5\ns=9\nbreak\ncase 12:s=25\nreturn A.c(o.bZ(b.a(l)),$async$T)\ncase 25:k=B.h\ns=9\nbreak\ncase 13:s=26\nreturn A.c(o.c_(b.a(l)),$async$T)\ncase 26:k=a5\ns=9\nbreak\ncase 14:s=27\nreturn A.c(o.cJ(c.a(l)),$async$T)\ncase 27:k=a5\ns=9\nbreak\ncase 15:s=28\nreturn A.c(o.cL(c.a(l)),$async$T)\ncase 28:k=a5\ns=9\nbreak\ncase 16:s=29\nreturn A.c(o.cG(c.a(l)),$async$T)\ncase 29:k=B.h\ns=9\nbreak\ncase 17:s=30\nreturn A.c(o.cH(c.a(l)),$async$T)\ncase 30:k=a5\ns=9\nbreak\ncase 18:s=31\nreturn A.c(o.cK(c.a(l)),$async$T)\ncase 31:k=a5\ns=9\nbreak\ncase 19:s=32\nreturn A.c(o.ea(c.a(l)),$async$T)\ncase 32:k=a5\ns=9\nbreak\ncase 20:s=33\nreturn A.c(o.cI(c.a(l)),$async$T)\ncase 33:k=a5\ns=9\nbreak\ncase 21:s=34\nreturn A.c(o.eb(c.a(l)),$async$T)\ncase 34:k=a5\ns=9\nbreak\ncase 22:k=B.h\no.e=!0\nB.c.aa(A.ay(f,!0,e),d)\ns=9\nbreak\ncase 9:g.hq(k)\nn=0\nq=1\ns=7\nbreak\ncase 5:q=4\na3=p\na1=A.E(a3)\nif(a1 instanceof A.aI){j=a1\nA.u(j)\nA.u(m)\nA.u(l)\nn=j.a}else{i=a1\nA.u(i)\nA.u(m)\nA.u(l)\nn=1}s=7\nbreak\ncase 4:s=1\nbreak\ncase 7:a1=n\na0.Atomics.store(h,1,a1)\na0.Atomics.notify(h,1,1/0)\ns=2\nbreak\ncase 3:return A.m(null,r)\ncase 1:return A.l(p,r)}})\nreturn A.n($async$T,r)},\niS(a){if(this.r.A(0,a))this.dA(a)},\naS(a){return this.iL(a)},\niL(a){var s=0,r=A.o(t.m),q,p=2,o,n=this,m,l,k,j,i,h,g,f,e,d\nvar $async$aS=A.p(function(b,c){if(b===1){o=c\ns=p}while(true)switch(s){case 0:e=a.x\nif(e!=null){q=e\ns=1\nbreak}m=1\nk=a.r,j=t.m,i=n.r\ncase 3:if(!!0){s=4\nbreak}p=6\ns=9\nreturn A.c(A.a_(k.createSyncAccessHandle(),j),$async$aS)\ncase 9:h=c\na.x=h\nl=h\nif(!a.w)i.v(0,a)\ng=l\nq=g\ns=1\nbreak\np=2\ns=8\nbreak\ncase 6:p=5\nd=o\nif(J.X(m,6))throw A.a(B.bm)\nA.u(m);++m\ns=8\nbreak\ncase 5:s=2\nbreak\ncase 8:s=3\nbreak\ncase 4:case 1:return A.m(q,r)\ncase 2:return A.l(o,r)}})\nreturn A.n($async$aS,r)},\ndA(a){var s\ntry{this.dz(a)}catch(s){}},\ndz(a){var s=a.x\nif(s!=null){a.x=null\nthis.r.A(0,a)\na.w=!1\ns.close()}}}\nA.dA.prototype={}\nA.fE.prototype={\ne_(a,b,c){var s=t.n\nreturn self.IDBKeyRange.bound(A.d([a,c],s),A.d([a,b],s))},\niO(a){return this.e_(a,9007199254740992,0)},\niP(a,b){return this.e_(a,9007199254740992,b)},\nd2(){var s=0,r=A.o(t.H),q=this,p,o\nvar $async$d2=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:p=new A.k($.i,t.et)\no=self.indexedDB.open(q.b,1)\no.onupgradeneeded=A.bb(new A.j1(o))\nnew A.a8(p,t.bh).L(A.tU(o,t.m))\ns=2\nreturn A.c(p,$async$d2)\ncase 2:q.a=b\nreturn A.m(null,r)}})\nreturn A.n($async$d2,r)},\np(){var s=this.a\nif(s!=null)s.close()},\nd1(){var s=0,r=A.o(t.g6),q,p=this,o,n,m,l,k\nvar $async$d1=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:l=A.a3(t.N,t.S)\nk=new A.cD(p.a.transaction(\"files\",\"readonly\").objectStore(\"files\").index(\"fileName\").openKeyCursor(),t.V)\ncase 3:s=5\nreturn A.c(k.k(),$async$d1)\ncase 5:if(!b){s=4\nbreak}o=k.a\nif(o==null)o=A.y(A.B(\"Await moveNext() first\"))\nn=o.key\nn.toString\nA.ad(n)\nm=o.primaryKey\nm.toString\nl.q(0,n,A.h(A.r(m)))\ns=3\nbreak\ncase 4:q=l\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$d1,r)},\ncV(a){return this.k_(a)},\nk_(a){var s=0,r=A.o(t.h6),q,p=this,o\nvar $async$cV=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:o=A\ns=3\nreturn A.c(A.bf(p.a.transaction(\"files\",\"readonly\").objectStore(\"files\").index(\"fileName\").getKey(a),t.i),$async$cV)\ncase 3:q=o.h(c)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$cV,r)},\ncS(a){return this.jJ(a)},\njJ(a){var s=0,r=A.o(t.S),q,p=this,o\nvar $async$cS=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:o=A\ns=3\nreturn A.c(A.bf(p.a.transaction(\"files\",\"readwrite\").objectStore(\"files\").put({name:a,length:0}),t.i),$async$cS)\ncase 3:q=o.h(c)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$cS,r)},\ne0(a,b){return A.bf(a.objectStore(\"files\").get(b),t.A).bF(new A.iZ(b),t.m)},\nbC(a){return this.kp(a)},\nkp(a){var s=0,r=A.o(t.p),q,p=this,o,n,m,l,k,j,i,h,g,f,e\nvar $async$bC=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:e=p.a\ne.toString\no=e.transaction($.ok(),\"readonly\")\nn=o.objectStore(\"blocks\")\ns=3\nreturn A.c(p.e0(o,a),$async$bC)\ncase 3:m=c\ne=m.length\nl=new Uint8Array(e)\nk=A.d([],t.fG)\nj=new A.cD(n.openCursor(p.iO(a)),t.V)\ne=t.H,i=t.c\ncase 4:s=6\nreturn A.c(j.k(),$async$bC)\ncase 6:if(!c){s=5\nbreak}h=j.a\nif(h==null)h=A.y(A.B(\"Await moveNext() first\"))\ng=i.a(h.key)\nf=A.h(A.r(g[1]))\nk.push(A.jW(new A.j2(h,l,f,Math.min(4096,m.length-f)),e))\ns=4\nbreak\ncase 5:s=7\nreturn A.c(A.ou(k,e),$async$bC)\ncase 7:q=l\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$bC,r)},\nb7(a,b){return this.jl(a,b)},\njl(a,b){var s=0,r=A.o(t.H),q=this,p,o,n,m,l,k,j\nvar $async$b7=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:j=q.a\nj.toString\np=j.transaction($.ok(),\"readwrite\")\no=p.objectStore(\"blocks\")\ns=2\nreturn A.c(q.e0(p,a),$async$b7)\ncase 2:n=d\nj=b.b\nm=A.t(j).h(\"b8<1>\")\nl=A.ay(new A.b8(j,m),!0,m.h(\"f.E\"))\nB.c.hB(l)\ns=3\nreturn A.c(A.ou(new A.D(l,new A.j_(new A.j0(o,a),b),A.Q(l).h(\"D<1,C<~>>\")),t.H),$async$b7)\ncase 3:s=b.c!==n.length?4:5\nbreak\ncase 4:k=new A.cD(p.objectStore(\"files\").openCursor(a),t.V)\ns=6\nreturn A.c(k.k(),$async$b7)\ncase 6:s=7\nreturn A.c(A.bf(k.gm().update({name:n.name,length:b.c}),t.X),$async$b7)\ncase 7:case 5:return A.m(null,r)}})\nreturn A.n($async$b7,r)},\nbi(a,b,c){return this.kF(0,b,c)},\nkF(a,b,c){var s=0,r=A.o(t.H),q=this,p,o,n,m,l,k\nvar $async$bi=A.p(function(d,e){if(d===1)return A.l(e,r)\nwhile(true)switch(s){case 0:k=q.a\nk.toString\np=k.transaction($.ok(),\"readwrite\")\no=p.objectStore(\"files\")\nn=p.objectStore(\"blocks\")\ns=2\nreturn A.c(q.e0(p,b),$async$bi)\ncase 2:m=e\ns=m.length>c?3:4\nbreak\ncase 3:s=5\nreturn A.c(A.bf(n.delete(q.iP(b,B.b.I(c,4096)*4096+1)),t.X),$async$bi)\ncase 5:case 4:l=new A.cD(o.openCursor(b),t.V)\ns=6\nreturn A.c(l.k(),$async$bi)\ncase 6:s=7\nreturn A.c(A.bf(l.gm().update({name:m.name,length:c}),t.X),$async$bi)\ncase 7:return A.m(null,r)}})\nreturn A.n($async$bi,r)},\ncU(a){return this.jL(a)},\njL(a){var s=0,r=A.o(t.H),q=this,p,o,n\nvar $async$cU=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:n=q.a\nn.toString\np=n.transaction(A.d([\"files\",\"blocks\"],t.s),\"readwrite\")\no=q.e_(a,9007199254740992,0)\nn=t.X\ns=2\nreturn A.c(A.ou(A.d([A.bf(p.objectStore(\"blocks\").delete(o),n),A.bf(p.objectStore(\"files\").delete(a),n)],t.fG),t.H),$async$cU)\ncase 2:return A.m(null,r)}})\nreturn A.n($async$cU,r)}}\nA.j1.prototype={\n$1(a){var s=t.m.a(this.a.result)\nif(J.X(a.oldVersion,0)){s.createObjectStore(\"files\",{autoIncrement:!0}).createIndex(\"fileName\",\"name\",{unique:!0})\ns.createObjectStore(\"blocks\")}},\n$S:10}\nA.iZ.prototype={\n$1(a){if(a==null)throw A.a(A.ag(this.a,\"fileId\",\"File not found in database\"))\nelse return a},\n$S:70}\nA.j2.prototype={\n$0(){var s=0,r=A.o(t.H),q=this,p,o,n,m\nvar $async$$0=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:p=B.e\no=q.b\nn=q.c\nm=A\ns=2\nreturn A.c(A.ky(t.m.a(q.a.value)),$async$$0)\ncase 2:p.aD(o,n,m.bj(b,0,q.d))\nreturn A.m(null,r)}})\nreturn A.n($async$$0,r)},\n$S:3}\nA.j0.prototype={\nhr(a,b){var s=0,r=A.o(t.H),q=this,p,o,n,m,l,k\nvar $async$$2=A.p(function(c,d){if(c===1)return A.l(d,r)\nwhile(true)switch(s){case 0:p=q.a\no=self\nn=q.b\nm=t.n\ns=2\nreturn A.c(A.bf(p.openCursor(o.IDBKeyRange.only(A.d([n,a],m))),t.A),$async$$2)\ncase 2:l=d\nk=new o.Blob(A.d([b],t.as))\no=t.X\ns=l==null?3:5\nbreak\ncase 3:s=6\nreturn A.c(A.bf(p.put(k,A.d([n,a],m)),o),$async$$2)\ncase 6:s=4\nbreak\ncase 5:s=7\nreturn A.c(A.bf(l.update(k),o),$async$$2)\ncase 7:case 4:return A.m(null,r)}})\nreturn A.n($async$$2,r)},\n$2(a,b){return this.hr(a,b)},\n$S:71}\nA.j_.prototype={\n$1(a){var s=this.b.b.i(0,a)\ns.toString\nreturn this.a.$2(a,s)},\n$S:72}\nA.mh.prototype={\nji(a,b,c){B.e.aD(this.b.hg(a,new A.mi(this,a)),b,c)},\njA(a,b){var s,r,q,p,o,n,m,l,k\nfor(s=b.length,r=0;r<s;){q=a+r\np=B.b.I(q,4096)\no=B.b.aA(q,4096)\nn=s-r\nif(o!==0)m=Math.min(4096-o,n)\nelse{m=Math.min(4096,n)\no=0}n=b.buffer\nl=b.byteOffset\nk=new Uint8Array(n,l+r,m)\nr+=m\nthis.ji(p*4096,o,k)}this.c=Math.max(this.c,a+s)}}\nA.mi.prototype={\n$0(){var s=new Uint8Array(4096),r=this.a.a,q=r.length,p=this.b\nif(q>p)B.e.aD(s,0,A.bj(r.buffer,r.byteOffset+p,Math.min(4096,q-p)))\nreturn s},\n$S:73}\nA.iq.prototype={}\nA.cY.prototype={\nbX(a){var s=this\nif(s.e||s.d.a==null)A.y(A.cz(10))\nif(a.ew(s.w)){s.fJ()\nreturn a.d.a}else return A.aX(null,t.H)},\nfJ(){var s,r,q=this\nif(q.f==null&&!q.w.gF(0)){s=q.w\nr=q.f=s.gG(0)\ns.A(0,r)\nr.d.L(A.u8(r.gd7(),t.H).ai(new A.k2(q)))}},\np(){var s=0,r=A.o(t.H),q,p=this,o,n\nvar $async$p=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:if(!p.e){o=p.bX(new A.dt(p.d.gb9(),new A.a8(new A.k($.i,t.D),t.F)))\np.e=!0\nq=o\ns=1\nbreak}else{n=p.w\nif(!n.gF(0)){q=n.gC(0).d.a\ns=1\nbreak}}case 1:return A.m(q,r)}})\nreturn A.n($async$p,r)},\nbr(a){return this.ii(a)},\nii(a){var s=0,r=A.o(t.S),q,p=this,o,n\nvar $async$br=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:n=p.y\ns=n.a4(a)?3:5\nbreak\ncase 3:n=n.i(0,a)\nn.toString\nq=n\ns=1\nbreak\ns=4\nbreak\ncase 5:s=6\nreturn A.c(p.d.cV(a),$async$br)\ncase 6:o=c\no.toString\nn.q(0,a,o)\nq=o\ns=1\nbreak\ncase 4:case 1:return A.m(q,r)}})\nreturn A.n($async$br,r)},\nbQ(){var s=0,r=A.o(t.H),q=this,p,o,n,m,l,k,j\nvar $async$bQ=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:m=q.d\ns=2\nreturn A.c(m.d1(),$async$bQ)\ncase 2:l=b\nq.y.aJ(0,l)\np=l.gel(),p=p.gt(p),o=q.r.d\ncase 3:if(!p.k()){s=4\nbreak}n=p.gm()\nk=o\nj=n.a\ns=5\nreturn A.c(m.bC(n.b),$async$bQ)\ncase 5:k.q(0,j,b)\ns=3\nbreak\ncase 4:return A.m(null,r)}})\nreturn A.n($async$bQ,r)},\nck(a,b){return this.r.d.a4(a)?1:0},\nda(a,b){var s=this\ns.r.d.A(0,a)\nif(!s.x.A(0,a))s.bX(new A.dr(s,a,new A.a8(new A.k($.i,t.D),t.F)))},\ndc(a){return $.fw().bA(\"/\"+a)},\naZ(a,b){var s,r,q,p=this,o=a.a\nif(o==null)o=A.ov(p.b,\"/\")\ns=p.r\nr=s.d.a4(o)?1:0\nq=s.aZ(new A.ez(o),b)\nif(r===0)if((b&8)!==0)p.x.v(0,o)\nelse p.bX(new A.cC(p,o,new A.a8(new A.k($.i,t.D),t.F)))\nreturn new A.cH(new A.ij(p,q.a,o),0)},\nde(a){}}\nA.k2.prototype={\n$0(){var s=this.a\ns.f=null\ns.fJ()},\n$S:9}\nA.ij.prototype={\neQ(a,b){this.b.eQ(a,b)},\ngeP(){return 0},\nd9(){return this.b.d>=2?1:0},\ncl(){},\ncm(){return this.b.cm()},\ndd(a){this.b.d=a\nreturn null},\ndf(a){},\ncn(a){var s=this,r=s.a\nif(r.e||r.d.a==null)A.y(A.cz(10))\ns.b.cn(a)\nif(!r.x.M(0,s.c))r.bX(new A.dt(new A.mw(s,a),new A.a8(new A.k($.i,t.D),t.F)))},\ndg(a){this.b.d=a\nreturn null},\nbH(a,b){var s,r,q,p,o,n=this.a\nif(n.e||n.d.a==null)A.y(A.cz(10))\ns=this.c\nr=n.r.d.i(0,s)\nif(r==null)r=new Uint8Array(0)\nthis.b.bH(a,b)\nif(!n.x.M(0,s)){q=new Uint8Array(a.length)\nB.e.aD(q,0,a)\np=A.d([],t.gQ)\no=$.i\np.push(new A.iq(b,q))\nn.bX(new A.cK(n,s,r,p,new A.a8(new A.k(o,t.D),t.F)))}},\n$idj:1}\nA.mw.prototype={\n$0(){var s=0,r=A.o(t.H),q,p=this,o,n,m\nvar $async$$0=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:o=p.a\nn=o.a\nm=n.d\ns=3\nreturn A.c(n.br(o.c),$async$$0)\ncase 3:q=m.bi(0,b,p.b)\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$$0,r)},\n$S:3}\nA.ao.prototype={\new(a){a.dT(a.c,this,!1)\nreturn!0}}\nA.dt.prototype={\nU(){return this.w.$0()}}\nA.dr.prototype={\new(a){var s,r,q,p\nif(!a.gF(0)){s=a.gC(0)\nfor(r=this.x;s!=null;)if(s instanceof A.dr)if(s.x===r)return!1\nelse s=s.gcc()\nelse if(s instanceof A.cK){q=s.gcc()\nif(s.x===r){p=s.a\np.toString\np.e4(A.t(s).h(\"aF.E\").a(s))}s=q}else if(s instanceof A.cC){if(s.x===r){r=s.a\nr.toString\nr.e4(A.t(s).h(\"aF.E\").a(s))\nreturn!1}s=s.gcc()}else break}a.dT(a.c,this,!1)\nreturn!0},\nU(){var s=0,r=A.o(t.H),q=this,p,o,n\nvar $async$U=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:p=q.w\no=q.x\ns=2\nreturn A.c(p.br(o),$async$U)\ncase 2:n=b\np.y.A(0,o)\ns=3\nreturn A.c(p.d.cU(n),$async$U)\ncase 3:return A.m(null,r)}})\nreturn A.n($async$U,r)}}\nA.cC.prototype={\nU(){var s=0,r=A.o(t.H),q=this,p,o,n,m\nvar $async$U=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:p=q.w\no=q.x\nn=p.y\nm=o\ns=2\nreturn A.c(p.d.cS(o),$async$U)\ncase 2:n.q(0,m,b)\nreturn A.m(null,r)}})\nreturn A.n($async$U,r)}}\nA.cK.prototype={\new(a){var s,r=a.b===0?null:a.gC(0)\nfor(s=this.x;r!=null;)if(r instanceof A.cK)if(r.x===s){B.c.aJ(r.z,this.z)\nreturn!1}else r=r.gcc()\nelse if(r instanceof A.cC){if(r.x===s)break\nr=r.gcc()}else break\na.dT(a.c,this,!1)\nreturn!0},\nU(){var s=0,r=A.o(t.H),q=this,p,o,n,m,l,k\nvar $async$U=A.p(function(a,b){if(a===1)return A.l(b,r)\nwhile(true)switch(s){case 0:m=q.y\nl=new A.mh(m,A.a3(t.S,t.p),m.length)\nfor(m=q.z,p=m.length,o=0;o<m.length;m.length===p||(0,A.W)(m),++o){n=m[o]\nl.jA(n.a,n.b)}m=q.w\nk=m.d\ns=3\nreturn A.c(m.br(q.x),$async$U)\ncase 3:s=2\nreturn A.c(k.b7(b,l),$async$U)\ncase 2:return A.m(null,r)}})\nreturn A.n($async$U,r)}}\nA.h2.prototype={\nck(a,b){return this.d.a4(a)?1:0},\nda(a,b){this.d.A(0,a)},\ndc(a){return $.fw().bA(\"/\"+a)},\naZ(a,b){var s,r=a.a\nif(r==null)r=A.ov(this.b,\"/\")\ns=this.d\nif(!s.a4(r))if((b&4)!==0)s.q(0,r,new Uint8Array(0))\nelse throw A.a(A.cz(14))\nreturn new A.cH(new A.ii(this,r,(b&8)!==0),0)},\nde(a){}}\nA.ii.prototype={\neI(a,b){var s,r=this.a.d.i(0,this.b)\nif(r==null||r.length<=b)return 0\ns=Math.min(a.length,r.length-b)\nB.e.Z(a,0,s,r,b)\nreturn s},\nd9(){return this.d>=2?1:0},\ncl(){if(this.c)this.a.d.A(0,this.b)},\ncm(){return this.a.d.i(0,this.b).length},\ndd(a){this.d=a},\ndf(a){},\ncn(a){var s=this.a.d,r=this.b,q=s.i(0,r),p=new Uint8Array(a)\nif(q!=null)B.e.aj(p,0,Math.min(a,q.length),q)\ns.q(0,r,p)},\ndg(a){this.d=a},\nbH(a,b){var s,r,q,p,o=this.a.d,n=this.b,m=o.i(0,n)\nif(m==null)m=new Uint8Array(0)\ns=b+a.length\nr=m.length\nq=s-r\nif(q<=0)B.e.aj(m,b,s,a)\nelse{p=new Uint8Array(r+q)\nB.e.aD(p,0,m)\nB.e.aD(p,b,a)\no.q(0,n,p)}}}\nA.cW.prototype={\nae(){return\"FileType.\"+this.b}}\nA.de.prototype={\ndU(a,b){var s=this.e,r=b?1:0\ns[a.a]=r\nA.ot(this.d,s,{at:0})},\nck(a,b){var s,r=$.ol().i(0,a)\nif(r==null)return this.r.d.a4(a)?1:0\nelse{s=this.e\nA.jM(this.d,s,{at:0})\nreturn s[r.a]}},\nda(a,b){var s=$.ol().i(0,a)\nif(s==null){this.r.d.A(0,a)\nreturn null}else this.dU(s,!1)},\ndc(a){return $.fw().bA(\"/\"+a)},\naZ(a,b){var s,r,q,p=this,o=a.a\nif(o==null)return p.r.aZ(a,b)\ns=$.ol().i(0,o)\nif(s==null)return p.r.aZ(a,b)\nr=p.e\nA.jM(p.d,r,{at:0})\nr=r[s.a]\nq=p.f.i(0,s)\nq.toString\nif(r===0)if((b&4)!==0){q.truncate(0)\np.dU(s,!0)}else throw A.a(B.ai)\nreturn new A.cH(new A.iz(p,s,q,(b&8)!==0),0)},\nde(a){},\np(){var s,r,q\nthis.d.close()\nfor(s=this.f.gaP(),r=A.t(s),s=new A.b0(J.M(s.a),s.b,r.h(\"b0<1,2>\")),r=r.y[1];s.k();){q=s.a\nif(q==null)q=r.a(q)\nq.close()}}}\nA.kQ.prototype={\nht(a){var s=0,r=A.o(t.m),q,p=this,o,n\nvar $async$$1=A.p(function(b,c){if(b===1)return A.l(c,r)\nwhile(true)switch(s){case 0:o=t.m\nn=A\ns=4\nreturn A.c(A.a_(p.a.getFileHandle(a,{create:!0}),o),$async$$1)\ncase 4:s=3\nreturn A.c(n.a_(c.createSyncAccessHandle(),o),$async$$1)\ncase 3:q=c\ns=1\nbreak\ncase 1:return A.m(q,r)}})\nreturn A.n($async$$1,r)},\n$1(a){return this.ht(a)},\n$S:74}\nA.iz.prototype={\neI(a,b){return A.jM(this.c,a,{at:b})},\nd9(){return this.e>=2?1:0},\ncl(){var s=this\ns.c.flush()\nif(s.d)s.a.dU(s.b,!1)},\ncm(){return this.c.getSize()},\ndd(a){this.e=a},\ndf(a){this.c.flush()},\ncn(a){this.c.truncate(a)},\ndg(a){this.e=a},\nbH(a,b){if(A.ot(this.c,a,{at:b})<a.length)throw A.a(B.aj)}}\nA.hS.prototype={\nc0(a,b){var s=J.V(a),r=A.h(A.r(this.d.call(null,s.gl(a)+b))),q=A.bj(this.b.buffer,0,null)\nB.e.aj(q,r,r+s.gl(a),a)\nB.e.en(q,r+s.gl(a),r+s.gl(a)+b,0)\nreturn r},\nbw(a){return this.c0(a,0)}}\nA.mx.prototype={\nhP(){var s=this,r=s.c=new self.WebAssembly.Memory({initial:16}),q=t.N,p=t.m\ns.b=A.kf([\"env\",A.kf([\"memory\",r],q,p),\"dart\",A.kf([\"error_log\",A.bb(new A.mN(r)),\"xOpen\",A.p7(new A.mO(s,r)),\"xDelete\",A.iK(new A.mP(s,r)),\"xAccess\",A.nR(new A.n_(s,r)),\"xFullPathname\",A.nR(new A.n5(s,r)),\"xRandomness\",A.iK(new A.n6(s,r)),\"xSleep\",A.cL(new A.n7(s)),\"xCurrentTimeInt64\",A.cL(new A.n8(s,r)),\"xDeviceCharacteristics\",A.bb(new A.n9(s)),\"xClose\",A.bb(new A.na(s)),\"xRead\",A.nR(new A.nb(s,r)),\"xWrite\",A.nR(new A.mQ(s,r)),\"xTruncate\",A.cL(new A.mR(s)),\"xSync\",A.cL(new A.mS(s)),\"xFileSize\",A.cL(new A.mT(s,r)),\"xLock\",A.cL(new A.mU(s)),\"xUnlock\",A.cL(new A.mV(s)),\"xCheckReservedLock\",A.cL(new A.mW(s,r)),\"function_xFunc\",A.iK(new A.mX(s)),\"function_xStep\",A.iK(new A.mY(s)),\"function_xInverse\",A.iK(new A.mZ(s)),\"function_xFinal\",A.bb(new A.n0(s)),\"function_xValue\",A.bb(new A.n1(s)),\"function_forget\",A.bb(new A.n2(s)),\"function_compare\",A.p7(new A.n3(s,r)),\"function_hook\",A.p7(new A.n4(s,r))],q,p)],q,t.dY)}}\nA.mN.prototype={\n$1(a){A.xq(\"[sqlite3] \"+A.c9(this.a,a,null))},\n$S:15}\nA.mO.prototype={\n$5(a,b,c,d,e){var s,r=this.a,q=r.d.e.i(0,a)\nq.toString\ns=this.b\nreturn A.aL(new A.mE(r,q,new A.ez(A.oM(s,b,null)),d,s,c,e))},\n$S:29}\nA.mE.prototype={\n$0(){var s,r=this,q=r.b.aZ(r.c,r.d),p=r.a.d.f,o=p.a\np.q(0,o,q.a)\np=r.e\nA.ct(p.buffer,0,null)[B.b.P(r.f,2)]=o\ns=r.r\nif(s!==0)A.ct(p.buffer,0,null)[B.b.P(s,2)]=q.b},\n$S:0}\nA.mP.prototype={\n$3(a,b,c){var s=this.a.d.e.i(0,a)\ns.toString\nreturn A.aL(new A.mD(s,A.c9(this.b,b,null),c))},\n$S:27}\nA.mD.prototype={\n$0(){return this.a.da(this.b,this.c)},\n$S:0}\nA.n_.prototype={\n$4(a,b,c,d){var s,r=this.a.d.e.i(0,a)\nr.toString\ns=this.b\nreturn A.aL(new A.mC(r,A.c9(s,b,null),c,s,d))},\n$S:31}\nA.mC.prototype={\n$0(){var s=this,r=s.a.ck(s.b,s.c)\nA.ct(s.d.buffer,0,null)[B.b.P(s.e,2)]=r},\n$S:0}\nA.n5.prototype={\n$4(a,b,c,d){var s,r=this.a.d.e.i(0,a)\nr.toString\ns=this.b\nreturn A.aL(new A.mB(r,A.c9(s,b,null),c,s,d))},\n$S:31}\nA.mB.prototype={\n$0(){var s,r,q=this,p=B.i.a5(q.a.dc(q.b)),o=p.length\nif(o>q.c)throw A.a(A.cz(14))\ns=A.bj(q.d.buffer,0,null)\nr=q.e\nB.e.aD(s,r,p)\ns[r+o]=0},\n$S:0}\nA.n6.prototype={\n$3(a,b,c){var s=this.a.d.e.i(0,a)\ns.toString\nreturn A.aL(new A.mM(s,this.b,c,b))},\n$S:27}\nA.mM.prototype={\n$0(){var s=this\ns.a.kH(A.bj(s.b.buffer,s.c,s.d))},\n$S:0}\nA.n7.prototype={\n$2(a,b){var s=this.a.d.e.i(0,a)\ns.toString\nreturn A.aL(new A.mL(s,b))},\n$S:4}\nA.mL.prototype={\n$0(){this.a.de(A.pJ(this.b,0))},\n$S:0}\nA.n8.prototype={\n$2(a,b){var s\nthis.a.d.e.i(0,a).toString\ns=Date.now()\ns=self.BigInt(s)\nA.ha(A.q_(this.b.buffer,0,null),\"setBigInt64\",b,s,!0,null)},\n$S:79}\nA.n9.prototype={\n$1(a){return this.a.d.f.i(0,a).geP()},\n$S:12}\nA.na.prototype={\n$1(a){var s=this.a,r=s.d.f.i(0,a)\nr.toString\nreturn A.aL(new A.mK(s,r,a))},\n$S:12}\nA.mK.prototype={\n$0(){this.b.cl()\nthis.a.d.f.A(0,this.c)},\n$S:0}\nA.nb.prototype={\n$4(a,b,c,d){var s=this.a.d.f.i(0,a)\ns.toString\nreturn A.aL(new A.mJ(s,this.b,b,c,d))},\n$S:32}\nA.mJ.prototype={\n$0(){var s=this\ns.a.eQ(A.bj(s.b.buffer,s.c,s.d),A.h(self.Number(s.e)))},\n$S:0}\nA.mQ.prototype={\n$4(a,b,c,d){var s=this.a.d.f.i(0,a)\ns.toString\nreturn A.aL(new A.mI(s,this.b,b,c,d))},\n$S:32}\nA.mI.prototype={\n$0(){var s=this\ns.a.bH(A.bj(s.b.buffer,s.c,s.d),A.h(self.Number(s.e)))},\n$S:0}\nA.mR.prototype={\n$2(a,b){var s=this.a.d.f.i(0,a)\ns.toString\nreturn A.aL(new A.mH(s,b))},\n$S:81}\nA.mH.prototype={\n$0(){return this.a.cn(A.h(self.Number(this.b)))},\n$S:0}\nA.mS.prototype={\n$2(a,b){var s=this.a.d.f.i(0,a)\ns.toString\nreturn A.aL(new A.mG(s,b))},\n$S:4}\nA.mG.prototype={\n$0(){return this.a.df(this.b)},\n$S:0}\nA.mT.prototype={\n$2(a,b){var s=this.a.d.f.i(0,a)\ns.toString\nreturn A.aL(new A.mF(s,this.b,b))},\n$S:4}\nA.mF.prototype={\n$0(){var s=this.a.cm()\nA.ct(this.b.buffer,0,null)[B.b.P(this.c,2)]=s},\n$S:0}\nA.mU.prototype={\n$2(a,b){var s=this.a.d.f.i(0,a)\ns.toString\nreturn A.aL(new A.mA(s,b))},\n$S:4}\nA.mA.prototype={\n$0(){return this.a.dd(this.b)},\n$S:0}\nA.mV.prototype={\n$2(a,b){var s=this.a.d.f.i(0,a)\ns.toString\nreturn A.aL(new A.mz(s,b))},\n$S:4}\nA.mz.prototype={\n$0(){return this.a.dg(this.b)},\n$S:0}\nA.mW.prototype={\n$2(a,b){var s=this.a.d.f.i(0,a)\ns.toString\nreturn A.aL(new A.my(s,this.b,b))},\n$S:4}\nA.my.prototype={\n$0(){var s=this.a.d9()\nA.ct(this.b.buffer,0,null)[B.b.P(this.c,2)]=s},\n$S:0}\nA.mX.prototype={\n$3(a,b,c){var s=this.a,r=s.a\nr===$&&A.G()\nr=s.d.b.i(0,A.h(A.r(r.xr.call(null,a)))).a\ns=s.a\nr.$2(new A.c7(s,a),new A.dk(s,b,c))},\n$S:18}\nA.mY.prototype={\n$3(a,b,c){var s=this.a,r=s.a\nr===$&&A.G()\nr=s.d.b.i(0,A.h(A.r(r.xr.call(null,a)))).b\ns=s.a\nr.$2(new A.c7(s,a),new A.dk(s,b,c))},\n$S:18}\nA.mZ.prototype={\n$3(a,b,c){var s=this.a,r=s.a\nr===$&&A.G()\ns.d.b.i(0,A.h(A.r(r.xr.call(null,a)))).toString\ns=s.a\nnull.$2(new A.c7(s,a),new A.dk(s,b,c))},\n$S:18}\nA.n0.prototype={\n$1(a){var s=this.a,r=s.a\nr===$&&A.G()\ns.d.b.i(0,A.h(A.r(r.xr.call(null,a)))).c.$1(new A.c7(s.a,a))},\n$S:15}\nA.n1.prototype={\n$1(a){var s=this.a,r=s.a\nr===$&&A.G()\ns.d.b.i(0,A.h(A.r(r.xr.call(null,a)))).toString\nnull.$1(new A.c7(s.a,a))},\n$S:15}\nA.n2.prototype={\n$1(a){this.a.d.b.A(0,a)},\n$S:15}\nA.n3.prototype={\n$5(a,b,c,d,e){var s=this.b,r=A.oM(s,c,b),q=A.oM(s,e,d)\nthis.a.d.b.i(0,a).toString\nreturn null.$2(r,q)},\n$S:29}\nA.n4.prototype={\n$5(a,b,c,d,e){A.c9(this.b,d,null)},\n$S:83}\nA.jp.prototype={\nkr(a){var s=this.a++\nthis.b.q(0,s,a)\nreturn s}}\nA.ht.prototype={}\nA.be.prototype={\nho(){var s=this.a\nreturn A.qj(new A.ed(s,new A.j8(),A.Q(s).h(\"ed<1,N>\")),null)},\nj(a){var s=this.a,r=A.Q(s)\nreturn new A.D(s,new A.j6(new A.D(s,new A.j7(),r.h(\"D<1,b>\")).eo(0,0,B.x)),r.h(\"D<1,j>\")).aq(0,u.q)},\n$ia0:1}\nA.j3.prototype={\n$1(a){return a.length!==0},\n$S:2}\nA.j8.prototype={\n$1(a){return a.gc3()},\n$S:84}\nA.j7.prototype={\n$1(a){var s=a.gc3()\nreturn new A.D(s,new A.j5(),A.Q(s).h(\"D<1,b>\")).eo(0,0,B.x)},\n$S:85}\nA.j5.prototype={\n$1(a){return a.gbz().length},\n$S:34}\nA.j6.prototype={\n$1(a){var s=a.gc3()\nreturn new A.D(s,new A.j4(this.a),A.Q(s).h(\"D<1,j>\")).c5(0)},\n$S:87}\nA.j4.prototype={\n$1(a){return B.a.hd(a.gbz(),this.a)+\"  \"+A.u(a.geC())+\"\\n\"},\n$S:35}\nA.N.prototype={\ngeA(){var s=this.a\nif(s.gY()===\"data\")return\"data:...\"\nreturn $.iQ().ko(s)},\ngbz(){var s,r=this,q=r.b\nif(q==null)return r.geA()\ns=r.c\nif(s==null)return r.geA()+\" \"+A.u(q)\nreturn r.geA()+\" \"+A.u(q)+\":\"+A.u(s)},\nj(a){return this.gbz()+\" in \"+A.u(this.d)},\ngeC(){return this.d}}\nA.jU.prototype={\n$0(){var s,r,q,p,o,n,m,l=null,k=this.a\nif(k===\"...\")return new A.N(A.aj(l,l,l,l),l,l,\"...\")\ns=$.tu().a9(k)\nif(s==null)return new A.bl(A.aj(l,\"unparsed\",l,l),k)\nk=s.b\nr=k[1]\nr.toString\nq=$.td()\nr=A.bc(r,q,\"<async>\")\np=A.bc(r,\"<anonymous closure>\",\"<fn>\")\nr=k[2]\nq=r\nq.toString\nif(B.a.u(q,\"<data:\"))o=A.qr(\"\")\nelse{r=r\nr.toString\no=A.bm(r)}n=k[3].split(\":\")\nk=n.length\nm=k>1?A.aN(n[1],l):l\nreturn new A.N(o,m,k>2?A.aN(n[2],l):l,p)},\n$S:11}\nA.jS.prototype={\n$0(){var s,r,q,p,o,n=\"<fn>\",m=this.a,l=$.tt().a9(m)\nif(l!=null){s=l.aN(\"member\")\nm=l.aN(\"uri\")\nm.toString\nr=A.h1(m)\nm=l.aN(\"index\")\nm.toString\nq=l.aN(\"offset\")\nq.toString\np=A.aN(q,16)\nif(!(s==null))m=s\nreturn new A.N(r,1,p+1,m)}l=$.tp().a9(m)\nif(l!=null){m=new A.jT(m)\nq=l.b\no=q[2]\nif(o!=null){o=o\no.toString\nq=q[1]\nq.toString\nq=A.bc(q,\"<anonymous>\",n)\nq=A.bc(q,\"Anonymous function\",n)\nreturn m.$2(o,A.bc(q,\"(anonymous function)\",n))}else{q=q[3]\nq.toString\nreturn m.$2(q,n)}}return new A.bl(A.aj(null,\"unparsed\",null,null),m)},\n$S:11}\nA.jT.prototype={\n$2(a,b){var s,r,q,p,o,n=null,m=$.to(),l=m.a9(a)\nfor(;l!=null;a=s){s=l.b[1]\ns.toString\nl=m.a9(s)}if(a===\"native\")return new A.N(A.bm(\"native\"),n,n,b)\nr=$.tq().a9(a)\nif(r==null)return new A.bl(A.aj(n,\"unparsed\",n,n),this.a)\nm=r.b\ns=m[1]\ns.toString\nq=A.h1(s)\ns=m[2]\ns.toString\np=A.aN(s,n)\no=m[3]\nreturn new A.N(q,p,o!=null?A.aN(o,n):n,b)},\n$S:90}\nA.jP.prototype={\n$0(){var s,r,q,p,o=null,n=this.a,m=$.te().a9(n)\nif(m==null)return new A.bl(A.aj(o,\"unparsed\",o,o),n)\nn=m.b\ns=n[1]\ns.toString\nr=A.bc(s,\"/<\",\"\")\ns=n[2]\ns.toString\nq=A.h1(s)\nn=n[3]\nn.toString\np=A.aN(n,o)\nreturn new A.N(q,p,o,r.length===0||r===\"anonymous\"?\"<fn>\":r)},\n$S:11}\nA.jQ.prototype={\n$0(){var s,r,q,p,o,n,m,l,k=null,j=this.a,i=$.tg().a9(j)\nif(i!=null){s=i.b\nr=s[3]\nq=r\nq.toString\nif(B.a.M(q,\" line \"))return A.u0(j)\nj=r\nj.toString\np=A.h1(j)\no=s[1]\nif(o!=null){j=s[2]\nj.toString\no+=B.c.c5(A.b_(B.a.ed(\"/\",j).gl(0),\".<fn>\",!1,t.N))\nif(o===\"\")o=\"<fn>\"\no=B.a.hl(o,$.tl(),\"\")}else o=\"<fn>\"\nj=s[4]\nif(j===\"\")n=k\nelse{j=j\nj.toString\nn=A.aN(j,k)}j=s[5]\nif(j==null||j===\"\")m=k\nelse{j=j\nj.toString\nm=A.aN(j,k)}return new A.N(p,n,m,o)}i=$.ti().a9(j)\nif(i!=null){j=i.aN(\"member\")\nj.toString\ns=i.aN(\"uri\")\ns.toString\np=A.h1(s)\ns=i.aN(\"index\")\ns.toString\nr=i.aN(\"offset\")\nr.toString\nl=A.aN(r,16)\nif(!(j.length!==0))j=s\nreturn new A.N(p,1,l+1,j)}i=$.tm().a9(j)\nif(i!=null){j=i.aN(\"member\")\nj.toString\nreturn new A.N(A.aj(k,\"wasm code\",k,k),k,k,j)}return new A.bl(A.aj(k,\"unparsed\",k,k),j)},\n$S:11}\nA.jR.prototype={\n$0(){var s,r,q,p,o=null,n=this.a,m=$.tj().a9(n)\nif(m==null)throw A.a(A.ai(\"Couldn't parse package:stack_trace stack trace line '\"+n+\"'.\",o,o))\nn=m.b\ns=n[1]\nif(s===\"data:...\")r=A.qr(\"\")\nelse{s=s\ns.toString\nr=A.bm(s)}if(r.gY()===\"\"){s=$.iQ()\nr=s.hp(s.fS(s.a.d3(A.pa(r)),o,o,o,o,o,o,o,o,o,o,o,o,o,o))}s=n[2]\nif(s==null)q=o\nelse{s=s\ns.toString\nq=A.aN(s,o)}s=n[3]\nif(s==null)p=o\nelse{s=s\ns.toString\np=A.aN(s,o)}return new A.N(r,q,p,n[4])},\n$S:11}\nA.hd.prototype={\ngfQ(){var s,r=this,q=r.b\nif(q===$){s=r.a.$0()\nr.b!==$&&A.oj()\nr.b=s\nq=s}return q},\ngc3(){return this.gfQ().gc3()},\nj(a){return this.gfQ().j(0)},\n$ia0:1,\n$ia1:1}\nA.a1.prototype={\nj(a){var s=this.a,r=A.Q(s)\nreturn new A.D(s,new A.l9(new A.D(s,new A.la(),r.h(\"D<1,b>\")).eo(0,0,B.x)),r.h(\"D<1,j>\")).c5(0)},\n$ia0:1,\ngc3(){return this.a}}\nA.l7.prototype={\n$0(){return A.qn(this.a.j(0))},\n$S:91}\nA.l8.prototype={\n$1(a){return a.length!==0},\n$S:2}\nA.l6.prototype={\n$1(a){return!B.a.u(a,$.ts())},\n$S:2}\nA.l5.prototype={\n$1(a){return a!==\"\\tat \"},\n$S:2}\nA.l3.prototype={\n$1(a){return a.length!==0&&a!==\"[native code]\"},\n$S:2}\nA.l4.prototype={\n$1(a){return!B.a.u(a,\"=====\")},\n$S:2}\nA.la.prototype={\n$1(a){return a.gbz().length},\n$S:34}\nA.l9.prototype={\n$1(a){if(a instanceof A.bl)return a.j(0)+\"\\n\"\nreturn B.a.hd(a.gbz(),this.a)+\"  \"+A.u(a.geC())+\"\\n\"},\n$S:35}\nA.bl.prototype={\nj(a){return this.w},\n$iN:1,\ngbz(){return\"unparsed\"},\ngeC(){return this.w}}\nA.e5.prototype={}\nA.eP.prototype={\nR(a,b,c,d){var s,r=this.b\nif(r.d){a=null\nd=null}s=this.a.R(a,b,c,d)\nif(!r.d)r.c=s\nreturn s},\naX(a,b,c){return this.R(a,null,b,c)},\neB(a,b){return this.R(a,null,b,null)}}\nA.eO.prototype={\np(){var s,r=this.hE(),q=this.b\nq.d=!0\ns=q.c\nif(s!=null){s.c9(null)\ns.eF(null)}return r}}\nA.ef.prototype={\nghD(){var s=this.b\ns===$&&A.G()\nreturn new A.an(s,A.t(s).h(\"an<1>\"))},\nghz(){var s=this.a\ns===$&&A.G()\nreturn s},\nhL(a,b,c,d){var s=this,r=$.i\ns.a!==$&&A.pq()\ns.a=new A.eY(a,s,new A.a2(new A.k(r,t.eI),t.fz),!0)\nr=A.eD(null,new A.k0(c,s),!0,d)\ns.b!==$&&A.pq()\ns.b=r},\niJ(){var s,r\nthis.d=!0\ns=this.c\nif(s!=null)s.J()\nr=this.b\nr===$&&A.G()\nr.p()}}\nA.k0.prototype={\n$0(){var s,r,q=this.b\nif(q.d)return\ns=this.a.a\nr=q.b\nr===$&&A.G()\nq.c=s.aX(r.gjy(r),new A.k_(q),r.gfT())},\n$S:0}\nA.k_.prototype={\n$0(){var s=this.a,r=s.a\nr===$&&A.G()\nr.iK()\ns=s.b\ns===$&&A.G()\ns.p()},\n$S:0}\nA.eY.prototype={\nv(a,b){if(this.e)throw A.a(A.B(\"Cannot add event after closing.\"))\nif(this.d)return\nthis.a.a.v(0,b)},\na3(a,b){if(this.e)throw A.a(A.B(\"Cannot add event after closing.\"))\nif(this.d)return\nthis.il(a,b)},\nil(a,b){this.a.a.a3(a,b)\nreturn},\np(){var s=this\nif(s.e)return s.c.a\ns.e=!0\nif(!s.d){s.b.iJ()\ns.c.L(s.a.a.p())}return s.c.a},\niK(){this.d=!0\nvar s=this.c\nif((s.a.a&30)===0)s.aV()\nreturn},\n$ia9:1}\nA.hC.prototype={}\nA.eC.prototype={}\nA.os.prototype={}\nA.eU.prototype={\nR(a,b,c,d){return A.aB(this.a,this.b,a,!1)},\naX(a,b,c){return this.R(a,null,b,c)}}\nA.ic.prototype={\nJ(){var s=this,r=A.aX(null,t.H)\nif(s.b==null)return r\ns.e5()\ns.d=s.b=null\nreturn r},\nc9(a){var s,r=this\nif(r.b==null)throw A.a(A.B(\"Subscription has been canceled.\"))\nr.e5()\nif(a==null)s=null\nelse{s=A.rt(new A.mf(a),t.m)\ns=s==null?null:A.bb(s)}r.d=s\nr.e3()},\neF(a){},\nbB(){if(this.b==null)return;++this.a\nthis.e5()},\nbf(){var s=this\nif(s.b==null||s.a<=0)return;--s.a\ns.e3()},\ne3(){var s=this,r=s.d\nif(r!=null&&s.a<=0)s.b.addEventListener(s.c,r,!1)},\ne5(){var s=this.d\nif(s!=null)this.b.removeEventListener(this.c,s,!1)}}\nA.me.prototype={\n$1(a){return this.a.$1(a)},\n$S:1}\nA.mf.prototype={\n$1(a){return this.a.$1(a)},\n$S:1};(function aliases(){var s=J.bY.prototype\ns.hG=s.j\ns=A.cA.prototype\ns.hI=s.bK\ns=A.af.prototype\ns.dm=s.bp\ns.bm=s.bn\ns.eW=s.cv\ns=A.fc.prototype\ns.hJ=s.ee\ns=A.z.prototype\ns.eV=s.Z\ns=A.f.prototype\ns.hF=s.hA\ns=A.cU.prototype\ns.hE=s.p\ns=A.ey.prototype\ns.hH=s.p})();(function installTearOffs(){var s=hunkHelpers._static_2,r=hunkHelpers._static_1,q=hunkHelpers._static_0,p=hunkHelpers.installStaticTearOff,o=hunkHelpers._instance_0u,n=hunkHelpers.installInstanceTearOff,m=hunkHelpers._instance_2u,l=hunkHelpers._instance_1i,k=hunkHelpers._instance_1u\ns(J,\"vZ\",\"ud\",92)\nr(A,\"wy\",\"uR\",21)\nr(A,\"wz\",\"uS\",21)\nr(A,\"wA\",\"uT\",21)\nq(A,\"rw\",\"wr\",0)\nr(A,\"wB\",\"wb\",16)\ns(A,\"wC\",\"wd\",6)\nq(A,\"rv\",\"wc\",0)\np(A,\"wI\",5,null,[\"$5\"],[\"wm\"],94,0)\np(A,\"wN\",4,null,[\"$1$4\",\"$4\"],[\"nT\",function(a,b,c,d){return A.nT(a,b,c,d,t.z)}],95,0)\np(A,\"wP\",5,null,[\"$2$5\",\"$5\"],[\"nV\",function(a,b,c,d,e){var i=t.z\nreturn A.nV(a,b,c,d,e,i,i)}],96,0)\np(A,\"wO\",6,null,[\"$3$6\",\"$6\"],[\"nU\",function(a,b,c,d,e,f){var i=t.z\nreturn A.nU(a,b,c,d,e,f,i,i,i)}],97,0)\np(A,\"wL\",4,null,[\"$1$4\",\"$4\"],[\"rm\",function(a,b,c,d){return A.rm(a,b,c,d,t.z)}],98,0)\np(A,\"wM\",4,null,[\"$2$4\",\"$4\"],[\"rn\",function(a,b,c,d){var i=t.z\nreturn A.rn(a,b,c,d,i,i)}],99,0)\np(A,\"wK\",4,null,[\"$3$4\",\"$4\"],[\"rl\",function(a,b,c,d){var i=t.z\nreturn A.rl(a,b,c,d,i,i,i)}],100,0)\np(A,\"wG\",5,null,[\"$5\"],[\"wl\"],101,0)\np(A,\"wQ\",4,null,[\"$4\"],[\"nW\"],102,0)\np(A,\"wF\",5,null,[\"$5\"],[\"wk\"],103,0)\np(A,\"wE\",5,null,[\"$5\"],[\"wj\"],104,0)\np(A,\"wJ\",4,null,[\"$4\"],[\"wn\"],105,0)\nr(A,\"wD\",\"wf\",106)\np(A,\"wH\",5,null,[\"$5\"],[\"rk\"],107,0)\nvar j\no(j=A.cB.prototype,\"gbN\",\"al\",0)\no(j,\"gbO\",\"am\",0)\nn(A.dp.prototype,\"gjI\",0,1,null,[\"$2\",\"$1\"],[\"bx\",\"aK\"],33,0,0)\nn(A.a2.prototype,\"gjH\",0,0,null,[\"$1\",\"$0\"],[\"L\",\"aV\"],77,0,0)\nm(A.k.prototype,\"gdB\",\"W\",6)\nl(j=A.cI.prototype,\"gjy\",\"v\",7)\nn(j,\"gfT\",0,1,null,[\"$2\",\"$1\"],[\"a3\",\"jz\"],33,0,0)\no(j=A.cb.prototype,\"gbN\",\"al\",0)\no(j,\"gbO\",\"am\",0)\no(j=A.af.prototype,\"gbN\",\"al\",0)\no(j,\"gbO\",\"am\",0)\no(A.eR.prototype,\"gfs\",\"iI\",0)\nk(j=A.dG.prototype,\"giC\",\"iD\",7)\nm(j,\"giG\",\"iH\",6)\no(j,\"giE\",\"iF\",0)\no(j=A.ds.prototype,\"gbN\",\"al\",0)\no(j,\"gbO\",\"am\",0)\nk(j,\"gdM\",\"dN\",7)\nm(j,\"gdQ\",\"dR\",117)\no(j,\"gdO\",\"dP\",0)\no(j=A.dD.prototype,\"gbN\",\"al\",0)\no(j,\"gbO\",\"am\",0)\nk(j,\"gdM\",\"dN\",7)\nm(j,\"gdQ\",\"dR\",6)\no(j,\"gdO\",\"dP\",0)\nk(A.dE.prototype,\"gjD\",\"ee\",\"Y<2>(e?)\")\nr(A,\"wU\",\"uO\",8)\np(A,\"xm\",2,null,[\"$1$2\",\"$2\"],[\"rF\",function(a,b){return A.rF(a,b,t.v)}],108,0)\nr(A,\"xo\",\"xu\",5)\nr(A,\"xn\",\"xt\",5)\nr(A,\"xl\",\"wV\",5)\nr(A,\"xp\",\"xA\",5)\nr(A,\"xi\",\"ww\",5)\nr(A,\"xj\",\"wx\",5)\nr(A,\"xk\",\"wR\",5)\nk(A.ea.prototype,\"gip\",\"iq\",7)\nk(A.fS.prototype,\"gi5\",\"dE\",13)\nk(A.hX.prototype,\"gjk\",\"e7\",13)\nr(A,\"yV\",\"rd\",20)\nr(A,\"yT\",\"rb\",20)\nr(A,\"yU\",\"rc\",20)\nr(A,\"rH\",\"we\",26)\nr(A,\"rI\",\"wh\",111)\nr(A,\"rG\",\"vO\",112)\no(A.dl.prototype,\"gb9\",\"p\",0)\nr(A,\"bQ\",\"uj\",113)\nr(A,\"b6\",\"uk\",114)\nr(A,\"pp\",\"ul\",115)\nk(A.eG.prototype,\"giR\",\"iS\",69)\no(A.fE.prototype,\"gb9\",\"p\",0)\no(A.cY.prototype,\"gb9\",\"p\",3)\no(A.dt.prototype,\"gd7\",\"U\",0)\no(A.dr.prototype,\"gd7\",\"U\",3)\no(A.cC.prototype,\"gd7\",\"U\",3)\no(A.cK.prototype,\"gd7\",\"U\",3)\no(A.de.prototype,\"gb9\",\"p\",0)\nr(A,\"x2\",\"u7\",17)\nr(A,\"rA\",\"u6\",17)\nr(A,\"x0\",\"u4\",17)\nr(A,\"x1\",\"u5\",17)\nr(A,\"xE\",\"uJ\",30)\nr(A,\"xD\",\"uI\",30)})();(function inheritance(){var s=hunkHelpers.mixin,r=hunkHelpers.inherit,q=hunkHelpers.inheritMany\nr(A.e,null)\nq(A.e,[A.oA,J.h7,J.fz,A.f,A.fJ,A.O,A.z,A.cl,A.kB,A.aZ,A.b0,A.eH,A.fY,A.hF,A.hy,A.hz,A.fV,A.hY,A.eg,A.ee,A.hJ,A.hE,A.f6,A.e7,A.il,A.lc,A.hp,A.ec,A.fa,A.T,A.ke,A.he,A.cs,A.dz,A.lO,A.dg,A.ns,A.m3,A.b1,A.ig,A.ny,A.iD,A.i_,A.iB,A.cS,A.Y,A.af,A.cA,A.dp,A.cc,A.k,A.i0,A.hD,A.cI,A.iC,A.i1,A.dH,A.ia,A.mc,A.f5,A.eR,A.dG,A.eT,A.dv,A.au,A.iI,A.dM,A.iH,A.ih,A.dd,A.ne,A.dy,A.io,A.aF,A.ip,A.cm,A.cn,A.nF,A.fm,A.a6,A.ie,A.fN,A.bp,A.md,A.hq,A.eA,A.id,A.bs,A.h6,A.bv,A.F,A.dI,A.av,A.fj,A.hN,A.b4,A.fZ,A.ho,A.nc,A.cU,A.fP,A.hf,A.hn,A.hK,A.ea,A.ir,A.fL,A.fT,A.fS,A.bZ,A.aH,A.bU,A.c1,A.bg,A.c3,A.bT,A.c4,A.c2,A.by,A.bA,A.kC,A.f7,A.hX,A.bC,A.bS,A.e3,A.al,A.e1,A.cR,A.kq,A.lb,A.ju,A.d6,A.kr,A.et,A.ko,A.bh,A.jv,A.lo,A.fU,A.db,A.lm,A.kK,A.fM,A.dB,A.dC,A.l1,A.km,A.eu,A.hA,A.cj,A.ku,A.hB,A.kv,A.kx,A.kw,A.d8,A.d9,A.br,A.jr,A.kR,A.cT,A.jo,A.ix,A.nh,A.cr,A.aI,A.ez,A.bF,A.fH,A.cD,A.hV,A.kz,A.bi,A.bw,A.it,A.eG,A.dA,A.fE,A.mh,A.iq,A.ij,A.hS,A.mx,A.jp,A.ht,A.be,A.N,A.hd,A.a1,A.bl,A.eC,A.eY,A.hC,A.os,A.ic])\nq(J.h7,[J.h8,J.ej,J.ek,J.aY,J.el,J.cZ,J.bV])\nq(J.ek,[J.bY,J.w,A.d_,A.ep])\nq(J.bY,[J.hr,J.cy,J.bW])\nr(J.k9,J.w)\nq(J.cZ,[J.ei,J.h9])\nq(A.f,[A.ca,A.v,A.az,A.aT,A.ed,A.cx,A.bB,A.ex,A.eI,A.bt,A.cG,A.hZ,A.iA,A.dJ,A.em])\nq(A.ca,[A.ck,A.fn])\nr(A.eS,A.ck)\nr(A.eN,A.fn)\nr(A.ah,A.eN)\nq(A.O,[A.bX,A.bD,A.hb,A.hI,A.i8,A.hv,A.ib,A.fC,A.aV,A.hL,A.hH,A.b2,A.fK])\nq(A.z,[A.dh,A.hQ,A.dk])\nr(A.e6,A.dh)\nq(A.cl,[A.j9,A.k3,A.ja,A.l2,A.kb,A.o6,A.o8,A.lQ,A.lP,A.nI,A.nt,A.nv,A.nu,A.jY,A.mn,A.mu,A.l_,A.kZ,A.kX,A.kV,A.nr,A.mb,A.ma,A.nm,A.nl,A.mv,A.ki,A.m0,A.nA,A.nO,A.nP,A.oa,A.oe,A.of,A.o1,A.jB,A.jC,A.jD,A.kH,A.kI,A.kJ,A.kF,A.lI,A.lF,A.lG,A.lD,A.lJ,A.lH,A.ks,A.jK,A.nX,A.kc,A.kd,A.kh,A.lA,A.lB,A.jx,A.o_,A.od,A.jE,A.kA,A.jf,A.jg,A.jh,A.kP,A.kL,A.kO,A.kM,A.kN,A.jm,A.jn,A.nY,A.lN,A.kS,A.o4,A.iY,A.m6,A.m7,A.jd,A.je,A.ji,A.jj,A.jk,A.j1,A.iZ,A.j_,A.kQ,A.mN,A.mO,A.mP,A.n_,A.n5,A.n6,A.n9,A.na,A.nb,A.mQ,A.mX,A.mY,A.mZ,A.n0,A.n1,A.n2,A.n3,A.n4,A.j3,A.j8,A.j7,A.j5,A.j6,A.j4,A.l8,A.l6,A.l5,A.l3,A.l4,A.la,A.l9,A.me,A.mf])\nq(A.j9,[A.oc,A.lR,A.lS,A.nx,A.nw,A.jX,A.jV,A.mj,A.mq,A.mp,A.mm,A.ml,A.mk,A.mt,A.ms,A.mr,A.l0,A.kY,A.kW,A.kU,A.nq,A.np,A.m2,A.m1,A.nf,A.nL,A.nM,A.m9,A.m8,A.nS,A.nk,A.nj,A.nE,A.nD,A.jA,A.kD,A.kE,A.kG,A.lK,A.lL,A.lE,A.og,A.lT,A.lY,A.lW,A.lX,A.lV,A.lU,A.nn,A.no,A.jz,A.jy,A.mg,A.kg,A.lC,A.jw,A.jI,A.jF,A.jG,A.jH,A.js,A.iW,A.iX,A.j2,A.mi,A.k2,A.mw,A.mE,A.mD,A.mC,A.mB,A.mM,A.mL,A.mK,A.mJ,A.mI,A.mH,A.mG,A.mF,A.mA,A.mz,A.my,A.jU,A.jS,A.jP,A.jQ,A.jR,A.l7,A.k0,A.k_])\nq(A.v,[A.P,A.cq,A.b8,A.cF,A.f_])\nq(A.P,[A.cw,A.D,A.ew])\nr(A.cp,A.az)\nr(A.eb,A.cx)\nr(A.cV,A.bB)\nr(A.co,A.bt)\nr(A.is,A.f6)\nq(A.is,[A.ap,A.cH])\nr(A.e8,A.e7)\nr(A.eh,A.k3)\nr(A.er,A.bD)\nq(A.l2,[A.kT,A.e2])\nq(A.T,[A.bu,A.cE])\nq(A.ja,[A.ka,A.o7,A.nJ,A.nZ,A.jZ,A.mo,A.nK,A.k1,A.kj,A.m_,A.lh,A.li,A.lj,A.nN,A.lr,A.lq,A.lp,A.jt,A.lu,A.lt,A.j0,A.n7,A.n8,A.mR,A.mS,A.mT,A.mU,A.mV,A.mW,A.jT])\nq(A.ep,[A.d0,A.d2])\nq(A.d2,[A.f1,A.f3])\nr(A.f2,A.f1)\nr(A.c_,A.f2)\nr(A.f4,A.f3)\nr(A.aR,A.f4)\nq(A.c_,[A.hg,A.hh])\nq(A.aR,[A.hi,A.d1,A.hj,A.hk,A.hl,A.eq,A.bx])\nr(A.fe,A.ib)\nq(A.Y,[A.dF,A.eW,A.eL,A.e0,A.eP,A.eU])\nr(A.an,A.dF)\nr(A.eM,A.an)\nq(A.af,[A.cb,A.ds,A.dD])\nr(A.cB,A.cb)\nr(A.fd,A.cA)\nq(A.dp,[A.a2,A.a8])\nq(A.cI,[A.dn,A.dK])\nq(A.ia,[A.dq,A.eQ])\nr(A.f0,A.eW)\nr(A.fc,A.hD)\nr(A.dE,A.fc)\nq(A.iH,[A.i7,A.iw])\nr(A.dw,A.cE)\nr(A.f8,A.dd)\nr(A.eZ,A.f8)\nq(A.cm,[A.fW,A.fF])\nq(A.fW,[A.fA,A.hO])\nq(A.cn,[A.iF,A.fG,A.hP])\nr(A.fB,A.iF)\nq(A.aV,[A.d7,A.h3])\nr(A.i9,A.fj)\nq(A.bZ,[A.am,A.ba,A.bq,A.bo])\nq(A.md,[A.d3,A.cv,A.c0,A.di,A.cu,A.d5,A.c8,A.bH,A.kl,A.ac,A.cW])\nr(A.jq,A.kq)\nr(A.kk,A.lb)\nq(A.ju,[A.hm,A.jJ])\nq(A.al,[A.i2,A.dx,A.hc])\nq(A.i2,[A.iE,A.fQ,A.i3,A.eV])\nr(A.fb,A.iE)\nr(A.ik,A.dx)\nr(A.ey,A.jq)\nr(A.f9,A.jJ)\nq(A.lo,[A.jb,A.dm,A.dc,A.da,A.eB,A.fR])\nq(A.jb,[A.c5,A.e9])\nr(A.m5,A.kr)\nr(A.hT,A.fQ)\nr(A.nH,A.ey)\nr(A.k7,A.l1)\nq(A.k7,[A.kn,A.lk,A.lM])\nq(A.br,[A.h_,A.cX])\nr(A.df,A.cT)\nr(A.iu,A.jo)\nr(A.iv,A.iu)\nr(A.hu,A.iv)\nr(A.iy,A.ix)\nr(A.bk,A.iy)\nr(A.fI,A.bF)\nr(A.lx,A.ku)\nr(A.ln,A.kv)\nr(A.lz,A.kx)\nr(A.ly,A.kw)\nr(A.c7,A.d8)\nr(A.bG,A.d9)\nr(A.hW,A.kR)\nq(A.fI,[A.dl,A.cY,A.h2,A.de])\nq(A.fH,[A.hU,A.ii,A.iz])\nq(A.bw,[A.aW,A.S])\nr(A.aQ,A.S)\nr(A.ao,A.aF)\nq(A.ao,[A.dt,A.dr,A.cC,A.cK])\nq(A.eC,[A.e5,A.ef])\nr(A.eO,A.cU)\ns(A.dh,A.hJ)\ns(A.fn,A.z)\ns(A.f1,A.z)\ns(A.f2,A.ee)\ns(A.f3,A.z)\ns(A.f4,A.ee)\ns(A.dn,A.i1)\ns(A.dK,A.iC)\ns(A.iu,A.z)\ns(A.iv,A.hn)\ns(A.ix,A.hK)\ns(A.iy,A.T)})()\nvar v={typeUniverse:{eC:new Map(),tR:{},eT:{},tPV:{},sEA:[]},mangledGlobalNames:{b:\"int\",I:\"double\",b5:\"num\",j:\"String\",U:\"bool\",F:\"Null\",q:\"List\",e:\"Object\",aa:\"Map\"},mangledNames:{},types:[\"~()\",\"~(A)\",\"U(j)\",\"C<~>()\",\"b(b,b)\",\"I(b5)\",\"~(e,a0)\",\"~(e?)\",\"j(j)\",\"F()\",\"F(A)\",\"N()\",\"b(b)\",\"e?(e?)\",\"C<F>()\",\"F(b)\",\"~(@)\",\"N(j)\",\"F(b,b,b)\",\"~(A?,q<A>?)\",\"j(b)\",\"~(~())\",\"U()\",\"~(at,j,b)\",\"U(~)\",\"F(@)\",\"b5?(q<e?>)\",\"b(b,b,b)\",\"@()\",\"b(b,b,b,b,b)\",\"a1(j)\",\"b(b,b,b,b)\",\"b(b,b,b,aY)\",\"~(e[a0?])\",\"b(N)\",\"j(N)\",\"C<b>()\",\"ba()\",\"am()\",\"F(U)\",\"bg()\",\"q<e?>(w<e?>)\",\"bC(e?)\",\"C<d6>()\",\"@(@)\",\"F(@,a0)\",\"b()\",\"C<U>()\",\"aa<j,@>(q<e?>)\",\"b(q<e?>)\",\"~(@,@)\",\"F(al)\",\"C<U>(~)\",\"~(e?,e?)\",\"~(b,@)\",\"F(~())\",\"A(w<e?>)\",\"db()\",\"C<at?>()\",\"C<al>()\",\"~(a9<e?>)\",\"~(U,U,U,q<+(bH,j)>)\",\"@(@,j)\",\"j(j?)\",\"j(e?)\",\"~(d8,q<d9>)\",\"~(br)\",\"~(j,aa<j,e?>)\",\"~(j,e?)\",\"~(dA)\",\"A(A?)\",\"C<~>(b,at)\",\"C<~>(b)\",\"at()\",\"C<A>(j)\",\"~(j,b)\",\"~(j,b?)\",\"~([e?])\",\"at(@,@)\",\"F(b,b)\",\"F(e,a0)\",\"b(b,aY)\",\"k<@>(@)\",\"F(b,b,b,b,aY)\",\"q<N>(a1)\",\"b(a1)\",\"C<~>(am)\",\"j(a1)\",\"b?(b)\",\"F(~)\",\"N(j,j)\",\"a1()\",\"b(@,@)\",\"bz?/(am)\",\"~(x?,Z?,x,e,a0)\",\"0^(x?,Z?,x,0^())<e?>\",\"0^(x?,Z?,x,0^(1^),1^)<e?,e?>\",\"0^(x?,Z?,x,0^(1^,2^),1^,2^)<e?,e?,e?>\",\"0^()(x,Z,x,0^())<e?>\",\"0^(1^)(x,Z,x,0^(1^))<e?,e?>\",\"0^(1^,2^)(x,Z,x,0^(1^,2^))<e?,e?,e?>\",\"cS?(x,Z,x,e,a0?)\",\"~(x?,Z?,x,~())\",\"eE(x,Z,x,bp,~())\",\"eE(x,Z,x,bp,~(eE))\",\"~(x,Z,x,j)\",\"~(j)\",\"x(x?,Z?,x,oO?,aa<e?,e?>?)\",\"0^(0^,0^)<b5>\",\"@(j)\",\"C<bz?>()\",\"U?(q<e?>)\",\"U(q<@>)\",\"aW(bi)\",\"S(bi)\",\"aQ(bi)\",\"bS<@>?()\",\"~(@,a0)\"],interceptorsByTag:null,leafTags:null,arrayRti:Symbol(\"$ti\"),rttc:{\"2;\":(a,b)=>c=>c instanceof A.ap&&a.b(c.a)&&b.b(c.b),\"2;file,outFlags\":(a,b)=>c=>c instanceof A.cH&&a.b(c.a)&&b.b(c.b)}}\nA.vk(v.typeUniverse,JSON.parse('{\"bW\":\"bY\",\"hr\":\"bY\",\"cy\":\"bY\",\"w\":{\"q\":[\"1\"],\"v\":[\"1\"],\"A\":[],\"f\":[\"1\"],\"ar\":[\"1\"]},\"h8\":{\"U\":[],\"L\":[]},\"ej\":{\"F\":[],\"L\":[]},\"ek\":{\"A\":[]},\"bY\":{\"A\":[]},\"k9\":{\"w\":[\"1\"],\"q\":[\"1\"],\"v\":[\"1\"],\"A\":[],\"f\":[\"1\"],\"ar\":[\"1\"]},\"cZ\":{\"I\":[],\"b5\":[]},\"ei\":{\"I\":[],\"b\":[],\"b5\":[],\"L\":[]},\"h9\":{\"I\":[],\"b5\":[],\"L\":[]},\"bV\":{\"j\":[],\"ar\":[\"@\"],\"L\":[]},\"ca\":{\"f\":[\"2\"]},\"ck\":{\"ca\":[\"1\",\"2\"],\"f\":[\"2\"],\"f.E\":\"2\"},\"eS\":{\"ck\":[\"1\",\"2\"],\"ca\":[\"1\",\"2\"],\"v\":[\"2\"],\"f\":[\"2\"],\"f.E\":\"2\"},\"eN\":{\"z\":[\"2\"],\"q\":[\"2\"],\"ca\":[\"1\",\"2\"],\"v\":[\"2\"],\"f\":[\"2\"]},\"ah\":{\"eN\":[\"1\",\"2\"],\"z\":[\"2\"],\"q\":[\"2\"],\"ca\":[\"1\",\"2\"],\"v\":[\"2\"],\"f\":[\"2\"],\"z.E\":\"2\",\"f.E\":\"2\"},\"bX\":{\"O\":[]},\"e6\":{\"z\":[\"b\"],\"q\":[\"b\"],\"v\":[\"b\"],\"f\":[\"b\"],\"z.E\":\"b\"},\"v\":{\"f\":[\"1\"]},\"P\":{\"v\":[\"1\"],\"f\":[\"1\"]},\"cw\":{\"P\":[\"1\"],\"v\":[\"1\"],\"f\":[\"1\"],\"f.E\":\"1\",\"P.E\":\"1\"},\"az\":{\"f\":[\"2\"],\"f.E\":\"2\"},\"cp\":{\"az\":[\"1\",\"2\"],\"v\":[\"2\"],\"f\":[\"2\"],\"f.E\":\"2\"},\"D\":{\"P\":[\"2\"],\"v\":[\"2\"],\"f\":[\"2\"],\"f.E\":\"2\",\"P.E\":\"2\"},\"aT\":{\"f\":[\"1\"],\"f.E\":\"1\"},\"ed\":{\"f\":[\"2\"],\"f.E\":\"2\"},\"cx\":{\"f\":[\"1\"],\"f.E\":\"1\"},\"eb\":{\"cx\":[\"1\"],\"v\":[\"1\"],\"f\":[\"1\"],\"f.E\":\"1\"},\"bB\":{\"f\":[\"1\"],\"f.E\":\"1\"},\"cV\":{\"bB\":[\"1\"],\"v\":[\"1\"],\"f\":[\"1\"],\"f.E\":\"1\"},\"ex\":{\"f\":[\"1\"],\"f.E\":\"1\"},\"cq\":{\"v\":[\"1\"],\"f\":[\"1\"],\"f.E\":\"1\"},\"eI\":{\"f\":[\"1\"],\"f.E\":\"1\"},\"bt\":{\"f\":[\"+(b,1)\"],\"f.E\":\"+(b,1)\"},\"co\":{\"bt\":[\"1\"],\"v\":[\"+(b,1)\"],\"f\":[\"+(b,1)\"],\"f.E\":\"+(b,1)\"},\"dh\":{\"z\":[\"1\"],\"q\":[\"1\"],\"v\":[\"1\"],\"f\":[\"1\"]},\"ew\":{\"P\":[\"1\"],\"v\":[\"1\"],\"f\":[\"1\"],\"f.E\":\"1\",\"P.E\":\"1\"},\"e7\":{\"aa\":[\"1\",\"2\"]},\"e8\":{\"e7\":[\"1\",\"2\"],\"aa\":[\"1\",\"2\"]},\"cG\":{\"f\":[\"1\"],\"f.E\":\"1\"},\"er\":{\"bD\":[],\"O\":[]},\"hb\":{\"O\":[]},\"hI\":{\"O\":[]},\"hp\":{\"a5\":[]},\"fa\":{\"a0\":[]},\"i8\":{\"O\":[]},\"hv\":{\"O\":[]},\"bu\":{\"T\":[\"1\",\"2\"],\"aa\":[\"1\",\"2\"],\"T.V\":\"2\",\"T.K\":\"1\"},\"b8\":{\"v\":[\"1\"],\"f\":[\"1\"],\"f.E\":\"1\"},\"dz\":{\"hs\":[],\"eo\":[]},\"hZ\":{\"f\":[\"hs\"],\"f.E\":\"hs\"},\"dg\":{\"eo\":[]},\"iA\":{\"f\":[\"eo\"],\"f.E\":\"eo\"},\"d_\":{\"A\":[],\"op\":[],\"L\":[]},\"d0\":{\"oq\":[],\"A\":[],\"L\":[]},\"d1\":{\"aR\":[],\"k5\":[],\"z\":[\"b\"],\"q\":[\"b\"],\"aP\":[\"b\"],\"v\":[\"b\"],\"A\":[],\"ar\":[\"b\"],\"f\":[\"b\"],\"L\":[],\"z.E\":\"b\"},\"bx\":{\"aR\":[],\"at\":[],\"z\":[\"b\"],\"q\":[\"b\"],\"aP\":[\"b\"],\"v\":[\"b\"],\"A\":[],\"ar\":[\"b\"],\"f\":[\"b\"],\"L\":[],\"z.E\":\"b\"},\"ep\":{\"A\":[]},\"d2\":{\"aP\":[\"1\"],\"A\":[],\"ar\":[\"1\"]},\"c_\":{\"z\":[\"I\"],\"q\":[\"I\"],\"aP\":[\"I\"],\"v\":[\"I\"],\"A\":[],\"ar\":[\"I\"],\"f\":[\"I\"]},\"aR\":{\"z\":[\"b\"],\"q\":[\"b\"],\"aP\":[\"b\"],\"v\":[\"b\"],\"A\":[],\"ar\":[\"b\"],\"f\":[\"b\"]},\"hg\":{\"c_\":[],\"jN\":[],\"z\":[\"I\"],\"q\":[\"I\"],\"aP\":[\"I\"],\"v\":[\"I\"],\"A\":[],\"ar\":[\"I\"],\"f\":[\"I\"],\"L\":[],\"z.E\":\"I\"},\"hh\":{\"c_\":[],\"jO\":[],\"z\":[\"I\"],\"q\":[\"I\"],\"aP\":[\"I\"],\"v\":[\"I\"],\"A\":[],\"ar\":[\"I\"],\"f\":[\"I\"],\"L\":[],\"z.E\":\"I\"},\"hi\":{\"aR\":[],\"k4\":[],\"z\":[\"b\"],\"q\":[\"b\"],\"aP\":[\"b\"],\"v\":[\"b\"],\"A\":[],\"ar\":[\"b\"],\"f\":[\"b\"],\"L\":[],\"z.E\":\"b\"},\"hj\":{\"aR\":[],\"k6\":[],\"z\":[\"b\"],\"q\":[\"b\"],\"aP\":[\"b\"],\"v\":[\"b\"],\"A\":[],\"ar\":[\"b\"],\"f\":[\"b\"],\"L\":[],\"z.E\":\"b\"},\"hk\":{\"aR\":[],\"le\":[],\"z\":[\"b\"],\"q\":[\"b\"],\"aP\":[\"b\"],\"v\":[\"b\"],\"A\":[],\"ar\":[\"b\"],\"f\":[\"b\"],\"L\":[],\"z.E\":\"b\"},\"hl\":{\"aR\":[],\"lf\":[],\"z\":[\"b\"],\"q\":[\"b\"],\"aP\":[\"b\"],\"v\":[\"b\"],\"A\":[],\"ar\":[\"b\"],\"f\":[\"b\"],\"L\":[],\"z.E\":\"b\"},\"eq\":{\"aR\":[],\"lg\":[],\"z\":[\"b\"],\"q\":[\"b\"],\"aP\":[\"b\"],\"v\":[\"b\"],\"A\":[],\"ar\":[\"b\"],\"f\":[\"b\"],\"L\":[],\"z.E\":\"b\"},\"ib\":{\"O\":[]},\"fe\":{\"bD\":[],\"O\":[]},\"cS\":{\"O\":[]},\"k\":{\"C\":[\"1\"]},\"um\":{\"a9\":[\"1\"]},\"af\":{\"af.T\":\"1\"},\"dv\":{\"a9\":[\"1\"]},\"dJ\":{\"f\":[\"1\"],\"f.E\":\"1\"},\"eM\":{\"an\":[\"1\"],\"dF\":[\"1\"],\"Y\":[\"1\"],\"Y.T\":\"1\"},\"cB\":{\"cb\":[\"1\"],\"af\":[\"1\"],\"af.T\":\"1\"},\"cA\":{\"a9\":[\"1\"]},\"fd\":{\"cA\":[\"1\"],\"a9\":[\"1\"]},\"a2\":{\"dp\":[\"1\"]},\"a8\":{\"dp\":[\"1\"]},\"cI\":{\"a9\":[\"1\"]},\"dn\":{\"cI\":[\"1\"],\"a9\":[\"1\"]},\"dK\":{\"cI\":[\"1\"],\"a9\":[\"1\"]},\"an\":{\"dF\":[\"1\"],\"Y\":[\"1\"],\"Y.T\":\"1\"},\"cb\":{\"af\":[\"1\"],\"af.T\":\"1\"},\"dH\":{\"a9\":[\"1\"]},\"dF\":{\"Y\":[\"1\"]},\"eW\":{\"Y\":[\"2\"]},\"ds\":{\"af\":[\"2\"],\"af.T\":\"2\"},\"f0\":{\"eW\":[\"1\",\"2\"],\"Y\":[\"2\"],\"Y.T\":\"2\"},\"eT\":{\"a9\":[\"1\"]},\"dD\":{\"af\":[\"2\"],\"af.T\":\"2\"},\"eL\":{\"Y\":[\"2\"],\"Y.T\":\"2\"},\"dE\":{\"fc\":[\"1\",\"2\"]},\"iI\":{\"oO\":[]},\"dM\":{\"Z\":[]},\"iH\":{\"x\":[]},\"i7\":{\"x\":[]},\"iw\":{\"x\":[]},\"cE\":{\"T\":[\"1\",\"2\"],\"aa\":[\"1\",\"2\"],\"T.V\":\"2\",\"T.K\":\"1\"},\"dw\":{\"cE\":[\"1\",\"2\"],\"T\":[\"1\",\"2\"],\"aa\":[\"1\",\"2\"],\"T.V\":\"2\",\"T.K\":\"1\"},\"cF\":{\"v\":[\"1\"],\"f\":[\"1\"],\"f.E\":\"1\"},\"eZ\":{\"f8\":[\"1\"],\"dd\":[\"1\"],\"v\":[\"1\"],\"f\":[\"1\"]},\"em\":{\"f\":[\"1\"],\"f.E\":\"1\"},\"z\":{\"q\":[\"1\"],\"v\":[\"1\"],\"f\":[\"1\"]},\"T\":{\"aa\":[\"1\",\"2\"]},\"f_\":{\"v\":[\"2\"],\"f\":[\"2\"],\"f.E\":\"2\"},\"dd\":{\"v\":[\"1\"],\"f\":[\"1\"]},\"f8\":{\"dd\":[\"1\"],\"v\":[\"1\"],\"f\":[\"1\"]},\"fA\":{\"cm\":[\"j\",\"q<b>\"]},\"iF\":{\"cn\":[\"j\",\"q<b>\"]},\"fB\":{\"cn\":[\"j\",\"q<b>\"]},\"fF\":{\"cm\":[\"q<b>\",\"j\"]},\"fG\":{\"cn\":[\"q<b>\",\"j\"]},\"fW\":{\"cm\":[\"j\",\"q<b>\"]},\"hO\":{\"cm\":[\"j\",\"q<b>\"]},\"hP\":{\"cn\":[\"j\",\"q<b>\"]},\"I\":{\"b5\":[]},\"b\":{\"b5\":[]},\"q\":{\"v\":[\"1\"],\"f\":[\"1\"]},\"hs\":{\"eo\":[]},\"fC\":{\"O\":[]},\"bD\":{\"O\":[]},\"aV\":{\"O\":[]},\"d7\":{\"O\":[]},\"h3\":{\"O\":[]},\"hL\":{\"O\":[]},\"hH\":{\"O\":[]},\"b2\":{\"O\":[]},\"fK\":{\"O\":[]},\"hq\":{\"O\":[]},\"eA\":{\"O\":[]},\"id\":{\"a5\":[]},\"bs\":{\"a5\":[]},\"h6\":{\"a5\":[],\"O\":[]},\"dI\":{\"a0\":[]},\"fj\":{\"hM\":[]},\"b4\":{\"hM\":[]},\"i9\":{\"hM\":[]},\"ho\":{\"a5\":[]},\"cU\":{\"a9\":[\"1\"]},\"fL\":{\"a5\":[]},\"fT\":{\"a5\":[]},\"am\":{\"bZ\":[]},\"ba\":{\"bZ\":[]},\"bg\":{\"as\":[]},\"by\":{\"as\":[]},\"aH\":{\"bz\":[]},\"bq\":{\"bZ\":[]},\"bo\":{\"bZ\":[]},\"d3\":{\"as\":[]},\"bU\":{\"as\":[]},\"c1\":{\"as\":[]},\"c3\":{\"as\":[]},\"bT\":{\"as\":[]},\"c4\":{\"as\":[]},\"c2\":{\"as\":[]},\"bA\":{\"bz\":[]},\"e3\":{\"a5\":[]},\"i2\":{\"al\":[]},\"iE\":{\"hG\":[],\"al\":[]},\"fb\":{\"hG\":[],\"al\":[]},\"fQ\":{\"al\":[]},\"i3\":{\"al\":[]},\"eV\":{\"al\":[]},\"dx\":{\"al\":[]},\"ik\":{\"hG\":[],\"al\":[]},\"hc\":{\"al\":[]},\"dm\":{\"a5\":[]},\"hT\":{\"al\":[]},\"eu\":{\"a5\":[]},\"hA\":{\"a5\":[]},\"h_\":{\"br\":[]},\"hQ\":{\"z\":[\"e?\"],\"q\":[\"e?\"],\"v\":[\"e?\"],\"f\":[\"e?\"],\"z.E\":\"e?\"},\"cX\":{\"br\":[]},\"df\":{\"cT\":[]},\"bk\":{\"T\":[\"j\",\"@\"],\"aa\":[\"j\",\"@\"],\"T.V\":\"@\",\"T.K\":\"j\"},\"hu\":{\"z\":[\"bk\"],\"q\":[\"bk\"],\"v\":[\"bk\"],\"f\":[\"bk\"],\"z.E\":\"bk\"},\"aI\":{\"a5\":[]},\"fI\":{\"bF\":[]},\"fH\":{\"dj\":[]},\"bG\":{\"d9\":[]},\"c7\":{\"d8\":[]},\"dk\":{\"z\":[\"bG\"],\"q\":[\"bG\"],\"v\":[\"bG\"],\"f\":[\"bG\"],\"z.E\":\"bG\"},\"e0\":{\"Y\":[\"1\"],\"Y.T\":\"1\"},\"dl\":{\"bF\":[]},\"hU\":{\"dj\":[]},\"aW\":{\"bw\":[]},\"S\":{\"bw\":[]},\"aQ\":{\"S\":[],\"bw\":[]},\"cY\":{\"bF\":[]},\"ao\":{\"aF\":[\"ao\"]},\"ij\":{\"dj\":[]},\"dt\":{\"ao\":[],\"aF\":[\"ao\"],\"aF.E\":\"ao\"},\"dr\":{\"ao\":[],\"aF\":[\"ao\"],\"aF.E\":\"ao\"},\"cC\":{\"ao\":[],\"aF\":[\"ao\"],\"aF.E\":\"ao\"},\"cK\":{\"ao\":[],\"aF\":[\"ao\"],\"aF.E\":\"ao\"},\"h2\":{\"bF\":[]},\"ii\":{\"dj\":[]},\"de\":{\"bF\":[]},\"iz\":{\"dj\":[]},\"be\":{\"a0\":[]},\"hd\":{\"a1\":[],\"a0\":[]},\"a1\":{\"a0\":[]},\"bl\":{\"N\":[]},\"e5\":{\"eC\":[\"1\"]},\"eP\":{\"Y\":[\"1\"],\"Y.T\":\"1\"},\"eO\":{\"a9\":[\"1\"]},\"ef\":{\"eC\":[\"1\"]},\"eY\":{\"a9\":[\"1\"]},\"eU\":{\"Y\":[\"1\"],\"Y.T\":\"1\"},\"k6\":{\"q\":[\"b\"],\"v\":[\"b\"],\"f\":[\"b\"]},\"at\":{\"q\":[\"b\"],\"v\":[\"b\"],\"f\":[\"b\"]},\"lg\":{\"q\":[\"b\"],\"v\":[\"b\"],\"f\":[\"b\"]},\"k4\":{\"q\":[\"b\"],\"v\":[\"b\"],\"f\":[\"b\"]},\"le\":{\"q\":[\"b\"],\"v\":[\"b\"],\"f\":[\"b\"]},\"k5\":{\"q\":[\"b\"],\"v\":[\"b\"],\"f\":[\"b\"]},\"lf\":{\"q\":[\"b\"],\"v\":[\"b\"],\"f\":[\"b\"]},\"jN\":{\"q\":[\"I\"],\"v\":[\"I\"],\"f\":[\"I\"]},\"jO\":{\"q\":[\"I\"],\"v\":[\"I\"],\"f\":[\"I\"]}}'))\nA.vj(v.typeUniverse,JSON.parse('{\"eH\":1,\"hy\":1,\"hz\":1,\"fV\":1,\"eg\":1,\"ee\":1,\"hJ\":1,\"dh\":1,\"fn\":2,\"he\":1,\"d2\":1,\"a9\":1,\"iB\":1,\"hD\":2,\"iC\":1,\"i1\":1,\"dH\":1,\"ia\":1,\"dq\":1,\"f5\":1,\"eR\":1,\"dG\":1,\"eT\":1,\"au\":1,\"fZ\":1,\"cU\":1,\"fP\":1,\"hf\":1,\"hn\":1,\"hK\":2,\"ey\":1,\"tJ\":1,\"hB\":1,\"eO\":1,\"eY\":1,\"ic\":1}'))\nvar u={q:\"===== asynchronous gap ===========================\\n\",l:\"Cannot extract a file path from a URI with a fragment component\",y:\"Cannot extract a file path from a URI with a query component\",j:\"Cannot extract a non-Windows file path from a file URI with an authority\",o:\"Cannot fire new event. Controller is already firing an event\",c:\"Error handler must accept one Object or one Object and a StackTrace as arguments, and return a value of the returned future's type\",D:\"Tried to operate on a released prepared statement\"}\nvar t=(function rtii(){var s=A.aq\nreturn{b9:s(\"tJ<e?>\"),cO:s(\"e0<w<e?>>\"),E:s(\"op\"),fd:s(\"oq\"),g1:s(\"bS<@>\"),eT:s(\"cT\"),ed:s(\"e9\"),gw:s(\"ea\"),Q:s(\"v<@>\"),q:s(\"aW\"),w:s(\"O\"),g8:s(\"a5\"),ez:s(\"cW\"),G:s(\"S\"),h4:s(\"jN\"),gN:s(\"jO\"),B:s(\"N\"),b8:s(\"xM\"),bF:s(\"C<U>\"),cG:s(\"C<bz?>\"),eY:s(\"C<at?>\"),bd:s(\"cY\"),dQ:s(\"k4\"),an:s(\"k5\"),gj:s(\"k6\"),dP:s(\"f<e?>\"),g7:s(\"w<cR>\"),cf:s(\"w<cT>\"),eV:s(\"w<cX>\"),e:s(\"w<N>\"),fG:s(\"w<C<~>>\"),fk:s(\"w<w<e?>>\"),W:s(\"w<A>\"),gP:s(\"w<q<@>>\"),gz:s(\"w<q<e?>>\"),d:s(\"w<aa<j,e?>>\"),eC:s(\"w<um<xR>>\"),as:s(\"w<bx>\"),f:s(\"w<e>\"),L:s(\"w<+(bH,j)>\"),bb:s(\"w<df>\"),s:s(\"w<j>\"),be:s(\"w<bC>\"),J:s(\"w<a1>\"),gQ:s(\"w<iq>\"),n:s(\"w<I>\"),gn:s(\"w<@>\"),t:s(\"w<b>\"),c:s(\"w<e?>\"),d4:s(\"w<j?>\"),r:s(\"w<I?>\"),Y:s(\"w<b?>\"),bT:s(\"w<~()>\"),aP:s(\"ar<@>\"),T:s(\"ej\"),m:s(\"A\"),C:s(\"aY\"),g:s(\"bW\"),aU:s(\"aP<@>\"),au:s(\"em<ao>\"),e9:s(\"q<w<e?>>\"),cl:s(\"q<A>\"),aS:s(\"q<aa<j,e?>>\"),o:s(\"q<j>\"),j:s(\"q<@>\"),I:s(\"q<b>\"),ee:s(\"q<e?>\"),dY:s(\"aa<j,A>\"),g6:s(\"aa<j,b>\"),cv:s(\"aa<e?,e?>\"),M:s(\"az<j,N>\"),fe:s(\"D<j,a1>\"),do:s(\"D<j,@>\"),fJ:s(\"bZ\"),cb:s(\"bw\"),eN:s(\"aQ\"),bZ:s(\"d_\"),gT:s(\"d0\"),ha:s(\"d1\"),aV:s(\"c_\"),eB:s(\"aR\"),Z:s(\"bx\"),bw:s(\"by\"),P:s(\"F\"),K:s(\"e\"),x:s(\"al\"),aj:s(\"d6\"),fl:s(\"xQ\"),bQ:s(\"+()\"),cz:s(\"hs\"),gy:s(\"ht\"),al:s(\"am\"),cc:s(\"bz\"),bJ:s(\"ew<j>\"),fE:s(\"db\"),fM:s(\"c5\"),gW:s(\"de\"),l:s(\"a0\"),a7:s(\"hC<e?>\"),N:s(\"j\"),aF:s(\"eE\"),a:s(\"a1\"),u:s(\"hG\"),dm:s(\"L\"),eK:s(\"bD\"),h7:s(\"le\"),bv:s(\"lf\"),go:s(\"lg\"),p:s(\"at\"),ak:s(\"cy\"),dD:s(\"hM\"),ei:s(\"eG\"),fL:s(\"bF\"),ga:s(\"dj\"),h2:s(\"hS\"),g9:s(\"hV\"),ab:s(\"hW\"),aT:s(\"dl\"),U:s(\"aT<j>\"),eJ:s(\"eI<j>\"),R:s(\"ac<S,aW>\"),dx:s(\"ac<S,S>\"),b0:s(\"ac<aQ,S>\"),bi:s(\"a2<c5>\"),co:s(\"a2<U>\"),fz:s(\"a2<@>\"),fu:s(\"a2<at?>\"),h:s(\"a2<~>\"),V:s(\"cD<A>\"),fF:s(\"eU<A>\"),et:s(\"k<A>\"),a9:s(\"k<c5>\"),k:s(\"k<U>\"),eI:s(\"k<@>\"),gR:s(\"k<b>\"),fX:s(\"k<at?>\"),D:s(\"k<~>\"),hg:s(\"dw<e?,e?>\"),cT:s(\"dA\"),aR:s(\"ir\"),eg:s(\"it\"),dn:s(\"fd<~>\"),bh:s(\"a8<A>\"),fa:s(\"a8<U>\"),F:s(\"a8<~>\"),y:s(\"U\"),i:s(\"I\"),z:s(\"@\"),bI:s(\"@(e)\"),b:s(\"@(e,a0)\"),S:s(\"b\"),aw:s(\"0&*\"),_:s(\"e*\"),eH:s(\"C<F>?\"),A:s(\"A?\"),dE:s(\"bx?\"),X:s(\"e?\"),ah:s(\"as?\"),O:s(\"bz?\"),aD:s(\"at?\"),h6:s(\"b?\"),v:s(\"b5\"),H:s(\"~\"),d5:s(\"~(e)\"),da:s(\"~(e,a0)\")}})();(function constants(){var s=hunkHelpers.makeConstList\nB.aG=J.h7.prototype\nB.c=J.w.prototype\nB.b=J.ei.prototype\nB.aH=J.cZ.prototype\nB.a=J.bV.prototype\nB.aI=J.bW.prototype\nB.aJ=J.ek.prototype\nB.e=A.bx.prototype\nB.ag=J.hr.prototype\nB.D=J.cy.prototype\nB.an=new A.cj(0)\nB.l=new A.cj(1)\nB.q=new A.cj(2)\nB.Y=new A.cj(3)\nB.bJ=new A.cj(-1)\nB.ao=new A.fB(127)\nB.x=new A.eh(A.xm(),A.aq(\"eh<b>\"))\nB.ap=new A.fA()\nB.bK=new A.fG()\nB.aq=new A.fF()\nB.Z=new A.e3()\nB.ar=new A.fL()\nB.bL=new A.fP()\nB.a_=new A.fS()\nB.a0=new A.fV()\nB.h=new A.aW()\nB.as=new A.h6()\nB.a1=function getTagFallback(o) {\n  var s = Object.prototype.toString.call(o);\n  return s.substring(8, s.length - 1);\n}\nB.at=function() {\n  var toStringFunction = Object.prototype.toString;\n  function getTag(o) {\n    var s = toStringFunction.call(o);\n    return s.substring(8, s.length - 1);\n  }\n  function getUnknownTag(object, tag) {\n    if (/^HTML[A-Z].*Element$/.test(tag)) {\n      var name = toStringFunction.call(object);\n      if (name == \"[object Object]\") return null;\n      return \"HTMLElement\";\n    }\n  }\n  function getUnknownTagGenericBrowser(object, tag) {\n    if (object instanceof HTMLElement) return \"HTMLElement\";\n    return getUnknownTag(object, tag);\n  }\n  function prototypeForTag(tag) {\n    if (typeof window == \"undefined\") return null;\n    if (typeof window[tag] == \"undefined\") return null;\n    var constructor = window[tag];\n    if (typeof constructor != \"function\") return null;\n    return constructor.prototype;\n  }\n  function discriminator(tag) { return null; }\n  var isBrowser = typeof HTMLElement == \"function\";\n  return {\n    getTag: getTag,\n    getUnknownTag: isBrowser ? getUnknownTagGenericBrowser : getUnknownTag,\n    prototypeForTag: prototypeForTag,\n    discriminator: discriminator };\n}\nB.ay=function(getTagFallback) {\n  return function(hooks) {\n    if (typeof navigator != \"object\") return hooks;\n    var userAgent = navigator.userAgent;\n    if (typeof userAgent != \"string\") return hooks;\n    if (userAgent.indexOf(\"DumpRenderTree\") >= 0) return hooks;\n    if (userAgent.indexOf(\"Chrome\") >= 0) {\n      function confirm(p) {\n        return typeof window == \"object\" && window[p] && window[p].name == p;\n      }\n      if (confirm(\"Window\") && confirm(\"HTMLElement\")) return hooks;\n    }\n    hooks.getTag = getTagFallback;\n  };\n}\nB.au=function(hooks) {\n  if (typeof dartExperimentalFixupGetTag != \"function\") return hooks;\n  hooks.getTag = dartExperimentalFixupGetTag(hooks.getTag);\n}\nB.ax=function(hooks) {\n  if (typeof navigator != \"object\") return hooks;\n  var userAgent = navigator.userAgent;\n  if (typeof userAgent != \"string\") return hooks;\n  if (userAgent.indexOf(\"Firefox\") == -1) return hooks;\n  var getTag = hooks.getTag;\n  var quickMap = {\n    \"BeforeUnloadEvent\": \"Event\",\n    \"DataTransfer\": \"Clipboard\",\n    \"GeoGeolocation\": \"Geolocation\",\n    \"Location\": \"!Location\",\n    \"WorkerMessageEvent\": \"MessageEvent\",\n    \"XMLDocument\": \"!Document\"};\n  function getTagFirefox(o) {\n    var tag = getTag(o);\n    return quickMap[tag] || tag;\n  }\n  hooks.getTag = getTagFirefox;\n}\nB.aw=function(hooks) {\n  if (typeof navigator != \"object\") return hooks;\n  var userAgent = navigator.userAgent;\n  if (typeof userAgent != \"string\") return hooks;\n  if (userAgent.indexOf(\"Trident/\") == -1) return hooks;\n  var getTag = hooks.getTag;\n  var quickMap = {\n    \"BeforeUnloadEvent\": \"Event\",\n    \"DataTransfer\": \"Clipboard\",\n    \"HTMLDDElement\": \"HTMLElement\",\n    \"HTMLDTElement\": \"HTMLElement\",\n    \"HTMLPhraseElement\": \"HTMLElement\",\n    \"Position\": \"Geoposition\"\n  };\n  function getTagIE(o) {\n    var tag = getTag(o);\n    var newTag = quickMap[tag];\n    if (newTag) return newTag;\n    if (tag == \"Object\") {\n      if (window.DataView && (o instanceof window.DataView)) return \"DataView\";\n    }\n    return tag;\n  }\n  function prototypeForTagIE(tag) {\n    var constructor = window[tag];\n    if (constructor == null) return null;\n    return constructor.prototype;\n  }\n  hooks.getTag = getTagIE;\n  hooks.prototypeForTag = prototypeForTagIE;\n}\nB.av=function(hooks) {\n  var getTag = hooks.getTag;\n  var prototypeForTag = hooks.prototypeForTag;\n  function getTagFixed(o) {\n    var tag = getTag(o);\n    if (tag == \"Document\") {\n      if (!!o.xmlVersion) return \"!Document\";\n      return \"!HTMLDocument\";\n    }\n    return tag;\n  }\n  function prototypeForTagFixed(tag) {\n    if (tag == \"Document\") return null;\n    return prototypeForTag(tag);\n  }\n  hooks.getTag = getTagFixed;\n  hooks.prototypeForTag = prototypeForTagFixed;\n}\nB.a2=function(hooks) { return hooks; }\n\nB.o=new A.hf()\nB.az=new A.kk()\nB.aA=new A.hm()\nB.aB=new A.hq()\nB.f=new A.kB()\nB.j=new A.hO()\nB.i=new A.hP()\nB.a3=new A.hX()\nB.y=new A.mc()\nB.d=new A.iw()\nB.z=new A.bp(0)\nB.aE=new A.bs(\"Cannot read message\",null,null)\nB.aF=new A.bs(\"Unknown tag\",null,null)\nB.aK=A.d(s([11]),t.t)\nB.aL=A.d(s([0,0,32722,12287,65534,34815,65534,18431]),t.t)\nB.p=A.d(s([0,0,65490,45055,65535,34815,65534,18431]),t.t)\nB.aM=A.d(s([0,0,32754,11263,65534,34815,65534,18431]),t.t)\nB.a4=A.d(s([0,0,26624,1023,65534,2047,65534,2047]),t.t)\nB.aN=A.d(s([0,0,32722,12287,65535,34815,65534,18431]),t.t)\nB.a5=A.d(s([0,0,65490,12287,65535,34815,65534,18431]),t.t)\nB.a6=A.d(s([0,0,32776,33792,1,10240,0,0]),t.t)\nB.F=new A.bH(0,\"opfs\")\nB.am=new A.bH(1,\"indexedDb\")\nB.aO=A.d(s([B.F,B.am]),A.aq(\"w<bH>\"))\nB.bj=new A.di(0,\"insert\")\nB.bk=new A.di(1,\"update\")\nB.bl=new A.di(2,\"delete\")\nB.a7=A.d(s([B.bj,B.bk,B.bl]),A.aq(\"w<di>\"))\nB.H=new A.ac(A.pp(),A.b6(),0,\"xAccess\",t.b0)\nB.G=new A.ac(A.pp(),A.bQ(),1,\"xDelete\",A.aq(\"ac<aQ,aW>\"))\nB.S=new A.ac(A.pp(),A.b6(),2,\"xOpen\",t.b0)\nB.Q=new A.ac(A.b6(),A.b6(),3,\"xRead\",t.dx)\nB.L=new A.ac(A.b6(),A.bQ(),4,\"xWrite\",t.R)\nB.M=new A.ac(A.b6(),A.bQ(),5,\"xSleep\",t.R)\nB.N=new A.ac(A.b6(),A.bQ(),6,\"xClose\",t.R)\nB.R=new A.ac(A.b6(),A.b6(),7,\"xFileSize\",t.dx)\nB.O=new A.ac(A.b6(),A.bQ(),8,\"xSync\",t.R)\nB.P=new A.ac(A.b6(),A.bQ(),9,\"xTruncate\",t.R)\nB.J=new A.ac(A.b6(),A.bQ(),10,\"xLock\",t.R)\nB.K=new A.ac(A.b6(),A.bQ(),11,\"xUnlock\",t.R)\nB.I=new A.ac(A.bQ(),A.bQ(),12,\"stopServer\",A.aq(\"ac<aW,aW>\"))\nB.aP=A.d(s([B.H,B.G,B.S,B.Q,B.L,B.M,B.N,B.R,B.O,B.P,B.J,B.K,B.I]),A.aq(\"w<ac<bw,bw>>\"))\nB.A=A.d(s([]),t.W)\nB.aQ=A.d(s([]),t.gz)\nB.aR=A.d(s([]),t.f)\nB.r=A.d(s([]),t.s)\nB.t=A.d(s([]),t.c)\nB.B=A.d(s([]),t.L)\nB.ak=new A.c8(0,\"opfsShared\")\nB.al=new A.c8(1,\"opfsLocks\")\nB.w=new A.c8(2,\"sharedIndexedDb\")\nB.E=new A.c8(3,\"unsafeIndexedDb\")\nB.bs=new A.c8(4,\"inMemory\")\nB.aT=A.d(s([B.ak,B.al,B.w,B.E,B.bs]),A.aq(\"w<c8>\"))\nB.b3=new A.cv(0,\"custom\")\nB.b4=new A.cv(1,\"deleteOrUpdate\")\nB.b5=new A.cv(2,\"insert\")\nB.b6=new A.cv(3,\"select\")\nB.a8=A.d(s([B.b3,B.b4,B.b5,B.b6]),A.aq(\"w<cv>\"))\nB.aD=new A.cW(\"/database\",0,\"database\")\nB.aC=new A.cW(\"/database-journal\",1,\"journal\")\nB.a9=A.d(s([B.aD,B.aC]),A.aq(\"w<cW>\"))\nB.ad=new A.c0(0,\"beginTransaction\")\nB.aV=new A.c0(1,\"commit\")\nB.aW=new A.c0(2,\"rollback\")\nB.ae=new A.c0(3,\"startExclusive\")\nB.af=new A.c0(4,\"endExclusive\")\nB.aa=A.d(s([B.ad,B.aV,B.aW,B.ae,B.af]),A.aq(\"w<c0>\"))\nB.ab=A.d(s([0,0,24576,1023,65534,34815,65534,18431]),t.t)\nB.m=new A.cu(0,\"sqlite\")\nB.b0=new A.cu(1,\"mysql\")\nB.b1=new A.cu(2,\"postgres\")\nB.b2=new A.cu(3,\"mariadb\")\nB.ac=A.d(s([B.m,B.b0,B.b1,B.b2]),A.aq(\"w<cu>\"))\nB.aX={}\nB.aU=new A.e8(B.aX,[],A.aq(\"e8<j,b>\"))\nB.C=new A.d3(0,\"terminateAll\")\nB.bM=new A.kl(2,\"readWriteCreate\")\nB.u=new A.d5(0,0,\"legacy\")\nB.aY=new A.d5(1,1,\"v1\")\nB.aZ=new A.d5(2,2,\"v2\")\nB.v=new A.d5(3,3,\"v3\")\nB.aS=A.d(s([]),t.d)\nB.b_=new A.bA(B.aS)\nB.ah=new A.hE(\"drift.runtime.cancellation\")\nB.b7=A.bd(\"op\")\nB.b8=A.bd(\"oq\")\nB.b9=A.bd(\"jN\")\nB.ba=A.bd(\"jO\")\nB.bb=A.bd(\"k4\")\nB.bc=A.bd(\"k5\")\nB.bd=A.bd(\"k6\")\nB.be=A.bd(\"e\")\nB.bf=A.bd(\"le\")\nB.bg=A.bd(\"lf\")\nB.bh=A.bd(\"lg\")\nB.bi=A.bd(\"at\")\nB.bm=new A.aI(10)\nB.bn=new A.aI(12)\nB.ai=new A.aI(14)\nB.bo=new A.aI(2570)\nB.bp=new A.aI(3850)\nB.bq=new A.aI(522)\nB.aj=new A.aI(778)\nB.br=new A.aI(8)\nB.T=new A.dB(\"above root\")\nB.U=new A.dB(\"at root\")\nB.bt=new A.dB(\"reaches root\")\nB.V=new A.dB(\"below root\")\nB.k=new A.dC(\"different\")\nB.W=new A.dC(\"equal\")\nB.n=new A.dC(\"inconclusive\")\nB.X=new A.dC(\"within\")\nB.bu=new A.dI(\"\")\nB.bv=new A.au(B.d,A.wI())\nB.bw=new A.au(B.d,A.wM())\nB.bx=new A.au(B.d,A.wF())\nB.by=new A.au(B.d,A.wG())\nB.bz=new A.au(B.d,A.wH())\nB.bA=new A.au(B.d,A.wJ())\nB.bB=new A.au(B.d,A.wL())\nB.bC=new A.au(B.d,A.wN())\nB.bD=new A.au(B.d,A.wO())\nB.bE=new A.au(B.d,A.wP())\nB.bF=new A.au(B.d,A.wQ())\nB.bG=new A.au(B.d,A.wE())\nB.bH=new A.au(B.d,A.wK())\nB.bI=new A.iI(null,null,null,null,null,null,null,null,null,null,null,null,null)})();(function staticFields(){$.nd=null\n$.cO=A.d([],t.f)\n$.rK=null\n$.q3=null\n$.pF=null\n$.pE=null\n$.rB=null\n$.ru=null\n$.rL=null\n$.o3=null\n$.o9=null\n$.pj=null\n$.ng=A.d([],A.aq(\"w<q<e>?>\"))\n$.dO=null\n$.fo=null\n$.fp=null\n$.p9=!1\n$.i=B.d\n$.ni=null\n$.qz=null\n$.qA=null\n$.qB=null\n$.qC=null\n$.oP=A.m4(\"_lastQuoRemDigits\")\n$.oQ=A.m4(\"_lastQuoRemUsed\")\n$.eK=A.m4(\"_lastRemUsed\")\n$.oR=A.m4(\"_lastRem_nsh\")\n$.qs=\"\"\n$.qt=null\n$.ra=null\n$.nQ=null})();(function lazyInitializers(){var s=hunkHelpers.lazyFinal,r=hunkHelpers.lazy\ns($,\"xH\",\"dX\",()=>A.x4(\"_$dart_dartClosure\"))\ns($,\"yX\",\"tx\",()=>B.d.bg(new A.oc(),A.aq(\"C<F>\")))\ns($,\"xX\",\"rU\",()=>A.bE(A.ld({\ntoString:function(){return\"$receiver$\"}})))\ns($,\"xY\",\"rV\",()=>A.bE(A.ld({$method$:null,\ntoString:function(){return\"$receiver$\"}})))\ns($,\"xZ\",\"rW\",()=>A.bE(A.ld(null)))\ns($,\"y_\",\"rX\",()=>A.bE(function(){var $argumentsExpr$=\"$arguments$\"\ntry{null.$method$($argumentsExpr$)}catch(q){return q.message}}()))\ns($,\"y2\",\"t_\",()=>A.bE(A.ld(void 0)))\ns($,\"y3\",\"t0\",()=>A.bE(function(){var $argumentsExpr$=\"$arguments$\"\ntry{(void 0).$method$($argumentsExpr$)}catch(q){return q.message}}()))\ns($,\"y1\",\"rZ\",()=>A.bE(A.qo(null)))\ns($,\"y0\",\"rY\",()=>A.bE(function(){try{null.$method$}catch(q){return q.message}}()))\ns($,\"y5\",\"t2\",()=>A.bE(A.qo(void 0)))\ns($,\"y4\",\"t1\",()=>A.bE(function(){try{(void 0).$method$}catch(q){return q.message}}()))\ns($,\"y7\",\"pt\",()=>A.uQ())\ns($,\"xO\",\"ci\",()=>A.aq(\"k<F>\").a($.tx()))\ns($,\"xN\",\"rS\",()=>A.v0(!1,B.d,t.y))\ns($,\"yh\",\"t8\",()=>{var q=t.z\nreturn A.pS(q,q)})\ns($,\"yl\",\"tc\",()=>A.q0(4096))\ns($,\"yj\",\"ta\",()=>new A.nE().$0())\ns($,\"yk\",\"tb\",()=>new A.nD().$0())\ns($,\"y8\",\"t3\",()=>A.un(A.iJ(A.d([-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-2,-2,-2,-2,-2,62,-2,62,-2,63,52,53,54,55,56,57,58,59,60,61,-2,-2,-2,-1,-2,-2,-2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-2,-2,-2,-2,63,-2,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,-2,-2,-2,-2,-2],t.t))))\ns($,\"yf\",\"b7\",()=>A.eJ(0))\ns($,\"yd\",\"fv\",()=>A.eJ(1))\ns($,\"ye\",\"t6\",()=>A.eJ(2))\ns($,\"yb\",\"pv\",()=>$.fv().aB(0))\ns($,\"y9\",\"pu\",()=>A.eJ(1e4))\nr($,\"yc\",\"t5\",()=>A.J(\"^\\\\s*([+-]?)((0x[a-f0-9]+)|(\\\\d+)|([a-z0-9]+))\\\\s*$\",!1,!1,!1,!1))\ns($,\"ya\",\"t4\",()=>A.q0(8))\ns($,\"yg\",\"t7\",()=>typeof FinalizationRegistry==\"function\"?FinalizationRegistry:null)\ns($,\"yi\",\"t9\",()=>A.J(\"^[\\\\-\\\\.0-9A-Z_a-z~]*$\",!0,!1,!1,!1))\ns($,\"yE\",\"om\",()=>A.pm(B.be))\ns($,\"yH\",\"tn\",()=>A.vP())\ns($,\"xP\",\"iP\",()=>{var q=new A.nc(new DataView(new ArrayBuffer(A.vN(8))))\nq.hQ()\nreturn q})\ns($,\"y6\",\"ps\",()=>A.tY(B.aO,A.aq(\"bH\")))\ns($,\"z0\",\"ty\",()=>A.jl(null,$.fu()))\ns($,\"yZ\",\"fw\",()=>A.jl(null,$.cP()))\ns($,\"yR\",\"iQ\",()=>new A.fM($.pr(),null))\ns($,\"xU\",\"rT\",()=>new A.kn(A.J(\"/\",!0,!1,!1,!1),A.J(\"[^/]$\",!0,!1,!1,!1),A.J(\"^/\",!0,!1,!1,!1)))\ns($,\"xW\",\"fu\",()=>new A.lM(A.J(\"[/\\\\\\\\]\",!0,!1,!1,!1),A.J(\"[^/\\\\\\\\]$\",!0,!1,!1,!1),A.J(\"^(\\\\\\\\\\\\\\\\[^\\\\\\\\]+\\\\\\\\[^\\\\\\\\/]+|[a-zA-Z]:[/\\\\\\\\])\",!0,!1,!1,!1),A.J(\"^[/\\\\\\\\](?![/\\\\\\\\])\",!0,!1,!1,!1)))\ns($,\"xV\",\"cP\",()=>new A.lk(A.J(\"/\",!0,!1,!1,!1),A.J(\"(^[a-zA-Z][-+.a-zA-Z\\\\d]*://|[^/])$\",!0,!1,!1,!1),A.J(\"[a-zA-Z][-+.a-zA-Z\\\\d]*://[^/]*\",!0,!1,!1,!1),A.J(\"^/\",!0,!1,!1,!1)))\ns($,\"xT\",\"pr\",()=>A.uE())\ns($,\"yQ\",\"tw\",()=>A.pC(\"-9223372036854775808\"))\ns($,\"yP\",\"tv\",()=>A.pC(\"9223372036854775807\"))\ns($,\"yW\",\"dY\",()=>{var q=$.t7()\nq=q==null?null:new q(A.cf(A.xF(new A.o4(),A.aq(\"br\")),1))\nreturn new A.ie(q,A.aq(\"ie<br>\"))})\ns($,\"xG\",\"ok\",()=>A.ui(A.d([\"files\",\"blocks\"],t.s)))\ns($,\"xJ\",\"ol\",()=>{var q,p,o=A.a3(t.N,t.ez)\nfor(q=0;q<2;++q){p=B.a9[q]\no.q(0,p.c,p)}return o})\ns($,\"xI\",\"rP\",()=>new A.fZ(new WeakMap()))\ns($,\"yO\",\"tu\",()=>A.J(\"^#\\\\d+\\\\s+(\\\\S.*) \\\\((.+?)((?::\\\\d+){0,2})\\\\)$\",!0,!1,!1,!1))\ns($,\"yJ\",\"tp\",()=>A.J(\"^\\\\s*at (?:(\\\\S.*?)(?: \\\\[as [^\\\\]]+\\\\])? \\\\((.*)\\\\)|(.*))$\",!0,!1,!1,!1))\ns($,\"yK\",\"tq\",()=>A.J(\"^(.*?):(\\\\d+)(?::(\\\\d+))?$|native$\",!0,!1,!1,!1))\ns($,\"yN\",\"tt\",()=>A.J(\"^\\\\s*at (?:(?<member>.+) )?(?:\\\\(?(?:(?<uri>\\\\S+):wasm-function\\\\[(?<index>\\\\d+)\\\\]\\\\:0x(?<offset>[0-9a-fA-F]+))\\\\)?)$\",!0,!1,!1,!1))\ns($,\"yI\",\"to\",()=>A.J(\"^eval at (?:\\\\S.*?) \\\\((.*)\\\\)(?:, .*?:\\\\d+:\\\\d+)?$\",!0,!1,!1,!1))\ns($,\"yx\",\"te\",()=>A.J(\"(\\\\S+)@(\\\\S+) line (\\\\d+) >.* (Function|eval):\\\\d+:\\\\d+\",!0,!1,!1,!1))\ns($,\"yz\",\"tg\",()=>A.J(\"^(?:([^@(/]*)(?:\\\\(.*\\\\))?((?:/[^/]*)*)(?:\\\\(.*\\\\))?@)?(.*?):(\\\\d*)(?::(\\\\d*))?$\",!0,!1,!1,!1))\ns($,\"yB\",\"ti\",()=>A.J(\"^(?<member>.*?)@(?:(?<uri>\\\\S+).*?:wasm-function\\\\[(?<index>\\\\d+)\\\\]:0x(?<offset>[0-9a-fA-F]+))$\",!0,!1,!1,!1))\ns($,\"yG\",\"tm\",()=>A.J(\"^.*?wasm-function\\\\[(?<member>.*)\\\\]@\\\\[wasm code\\\\]$\",!0,!1,!1,!1))\ns($,\"yC\",\"tj\",()=>A.J(\"^(\\\\S+)(?: (\\\\d+)(?::(\\\\d+))?)?\\\\s+([^\\\\d].*)$\",!0,!1,!1,!1))\ns($,\"yw\",\"td\",()=>A.J(\"<(<anonymous closure>|[^>]+)_async_body>\",!0,!1,!1,!1))\ns($,\"yF\",\"tl\",()=>A.J(\"^\\\\.\",!0,!1,!1,!1))\ns($,\"xK\",\"rQ\",()=>A.J(\"^[a-zA-Z][-+.a-zA-Z\\\\d]*://\",!0,!1,!1,!1))\ns($,\"xL\",\"rR\",()=>A.J(\"^([a-zA-Z]:[\\\\\\\\/]|\\\\\\\\\\\\\\\\)\",!0,!1,!1,!1))\ns($,\"yL\",\"tr\",()=>A.J(\"\\\\n    ?at \",!0,!1,!1,!1))\ns($,\"yM\",\"ts\",()=>A.J(\"    ?at \",!0,!1,!1,!1))\ns($,\"yy\",\"tf\",()=>A.J(\"@\\\\S+ line \\\\d+ >.* (Function|eval):\\\\d+:\\\\d+\",!0,!1,!1,!1))\ns($,\"yA\",\"th\",()=>A.J(\"^(([.0-9A-Za-z_$/<]|\\\\(.*\\\\))*@)?[^\\\\s]*:\\\\d*$\",!0,!1,!0,!1))\ns($,\"yD\",\"tk\",()=>A.J(\"^[^\\\\s<][^\\\\s]*( \\\\d+(:\\\\d+)?)?[ \\\\t]+[^\\\\s]+$\",!0,!1,!0,!1))\ns($,\"z_\",\"pw\",()=>A.J(\"^<asynchronous suspension>\\\\n?$\",!0,!1,!0,!1))})();(function nativeSupport(){!function(){var s=function(a){var m={}\nm[a]=1\nreturn Object.keys(hunkHelpers.convertToFastObject(m))[0]}\nv.getIsolateTag=function(a){return s(\"___dart_\"+a+v.isolateTag)}\nvar r=\"___dart_isolate_tags_\"\nvar q=Object[r]||(Object[r]=Object.create(null))\nvar p=\"_ZxYxX\"\nfor(var o=0;;o++){var n=s(p+\"_\"+o+\"_\")\nif(!(n in q)){q[n]=1\nv.isolateTag=n\nbreak}}v.dispatchPropertyName=v.getIsolateTag(\"dispatch_record\")}()\nhunkHelpers.setOrUpdateInterceptorsByTag({ArrayBuffer:A.d_,ArrayBufferView:A.ep,DataView:A.d0,Float32Array:A.hg,Float64Array:A.hh,Int16Array:A.hi,Int32Array:A.d1,Int8Array:A.hj,Uint16Array:A.hk,Uint32Array:A.hl,Uint8ClampedArray:A.eq,CanvasPixelArray:A.eq,Uint8Array:A.bx})\nhunkHelpers.setOrUpdateLeafTags({ArrayBuffer:true,ArrayBufferView:false,DataView:true,Float32Array:true,Float64Array:true,Int16Array:true,Int32Array:true,Int8Array:true,Uint16Array:true,Uint32Array:true,Uint8ClampedArray:true,CanvasPixelArray:true,Uint8Array:false})\nA.d2.$nativeSuperclassTag=\"ArrayBufferView\"\nA.f1.$nativeSuperclassTag=\"ArrayBufferView\"\nA.f2.$nativeSuperclassTag=\"ArrayBufferView\"\nA.c_.$nativeSuperclassTag=\"ArrayBufferView\"\nA.f3.$nativeSuperclassTag=\"ArrayBufferView\"\nA.f4.$nativeSuperclassTag=\"ArrayBufferView\"\nA.aR.$nativeSuperclassTag=\"ArrayBufferView\"})()\nFunction.prototype.$0=function(){return this()}\nFunction.prototype.$1=function(a){return this(a)}\nFunction.prototype.$2=function(a,b){return this(a,b)}\nFunction.prototype.$1$1=function(a){return this(a)}\nFunction.prototype.$3=function(a,b,c){return this(a,b,c)}\nFunction.prototype.$4=function(a,b,c,d){return this(a,b,c,d)}\nFunction.prototype.$3$1=function(a){return this(a)}\nFunction.prototype.$2$1=function(a){return this(a)}\nFunction.prototype.$3$3=function(a,b,c){return this(a,b,c)}\nFunction.prototype.$2$2=function(a,b){return this(a,b)}\nFunction.prototype.$2$3=function(a,b,c){return this(a,b,c)}\nFunction.prototype.$1$2=function(a,b){return this(a,b)}\nFunction.prototype.$5=function(a,b,c,d,e){return this(a,b,c,d,e)}\nFunction.prototype.$6=function(a,b,c,d,e,f){return this(a,b,c,d,e,f)}\nFunction.prototype.$1$0=function(){return this()}\nconvertAllToFastObject(w)\nconvertToFastObject($);(function(a){if(typeof document===\"undefined\"){a(null)\nreturn}if(typeof document.currentScript!=\"undefined\"){a(document.currentScript)\nreturn}var s=document.scripts\nfunction onLoad(b){for(var q=0;q<s.length;++q){s[q].removeEventListener(\"load\",onLoad,false)}a(b.target)}for(var r=0;r<s.length;++r){s[r].addEventListener(\"load\",onLoad,false)}})(function(a){v.currentScript=a\nvar s=A.xg\nif(typeof dartMainRunner===\"function\"){dartMainRunner(s,[])}else{s([])}})})()\n//# sourceMappingURL=out.js.map\n"
  },
  {
    "path": "web/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <!--\n    If you are serving your web app in a path other than the root, change the\n    href value below to reflect the base path you are serving from.\n\n    The path provided below has to start and end with a slash \"/\" in order for\n    it to work correctly.\n\n    For more details:\n    * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base\n\n    This is a placeholder for base href that will be replaced by the value of\n    the `--base-href` argument provided to `flutter build`.\n  -->\n  <base href=\"$FLUTTER_BASE_HREF\">\n\n  <meta charset=\"UTF-8\">\n  <meta content=\"IE=Edge\" http-equiv=\"X-UA-Compatible\">\n  <meta name=\"description\" content=\"A new Flutter project.\">\n\n  <!-- iOS meta tags & icons -->\n  <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n  <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n  <meta name=\"apple-mobile-web-app-title\" content=\"myapp\">\n  <link rel=\"apple-touch-icon\" href=\"icons/Icon-192.png\">\n\n  <!-- Favicon -->\n  <link rel=\"icon\" type=\"image/png\" href=\"icon.png\"/>\n\n  <title>myapp</title>\n  <link rel=\"manifest\" href=\"manifest.json\">\n\n  <script>\n    // The value below is injected by flutter build, do not touch.\n    const serviceWorkerVersion = null;\n  </script>\n  <!-- This script adds the flutter initialization JS code -->\n  <script src=\"flutter.js\" defer></script>\n</head>\n<body>\n  <script>\n    window.addEventListener('load', function(ev) {\n      // Download main.dart.js\n      _flutter.loader.loadEntrypoint({\n        serviceWorker: {\n          serviceWorkerVersion: serviceWorkerVersion,\n        },\n        onEntrypointLoaded: function(engineInitializer) {\n          engineInitializer.initializeEngine().then(function(appRunner) {\n            appRunner.runApp();\n          });\n        }\n      });\n    });\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "web/manifest.json",
    "content": "{\n    \"name\": \"Hiddify\",\n    \"short_name\": \"Hiddify\",\n    \"start_url\": \".\",\n    \"display\": \"standalone\",\n    \"background_color\": \"#0175C2\",\n    \"theme_color\": \"#0175C2\",\n    \"description\": \"Hiddify\",\n    \"orientation\": \"portrait-primary\",\n    \"prefer_related_applications\": false,\n    \"icons\": [\n        {\n            \"src\": \"icon.png\",\n            \"sizes\": \"512x512\",\n            \"type\": \"image/png\"\n        }\n    ]\n}\n"
  },
  {
    "path": "windows/.gitignore",
    "content": "flutter/ephemeral/\n\n# Visual Studio user-specific files.\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# Visual Studio build-related files.\nx64/\nx86/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n"
  },
  {
    "path": "windows/.stignore",
    "content": "/flutter/ephemeral/\n\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n/x64/\n/x86/\n"
  },
  {
    "path": "windows/CMakeLists.txt",
    "content": "# Project-level configuration.\ncmake_minimum_required(VERSION 3.14)\nproject(hiddify LANGUAGES CXX)\n\n# The name of the executable created for the application. Change this to change\n# the on-disk name of your application.\nset(BINARY_NAME \"Hiddify\")\n\n# Explicitly opt in to modern CMake behaviors to avoid warnings with recent\n# versions of CMake.\ncmake_policy(SET CMP0063 NEW)\n\n# Define build configuration option.\nget_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)\nif(IS_MULTICONFIG)\n  set(CMAKE_CONFIGURATION_TYPES \"Debug;Profile;Release\"\n    CACHE STRING \"\" FORCE)\nelse()\n  if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)\n    set(CMAKE_BUILD_TYPE \"Debug\" CACHE\n      STRING \"Flutter build mode\" FORCE)\n    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS\n      \"Debug\" \"Profile\" \"Release\")\n  endif()\nendif()\n# Define settings for the Profile build mode.\nset(CMAKE_EXE_LINKER_FLAGS_PROFILE \"${CMAKE_EXE_LINKER_FLAGS_RELEASE}\")\nset(CMAKE_SHARED_LINKER_FLAGS_PROFILE \"${CMAKE_SHARED_LINKER_FLAGS_RELEASE}\")\nset(CMAKE_C_FLAGS_PROFILE \"${CMAKE_C_FLAGS_RELEASE}\")\nset(CMAKE_CXX_FLAGS_PROFILE \"${CMAKE_CXX_FLAGS_RELEASE}\")\n\n# Use Unicode for all projects.\nadd_definitions(-DUNICODE -D_UNICODE)\n\n# Compilation settings that should be applied to most targets.\n#\n# Be cautious about adding new options here, as plugins use this function by\n# default. In most cases, you should add new options to specific targets instead\n# of modifying this function.\nfunction(APPLY_STANDARD_SETTINGS TARGET)\n  target_compile_features(${TARGET} PUBLIC cxx_std_17)\n  target_compile_options(${TARGET} PRIVATE /W4 /WX /wd\"4100\")\n  target_compile_options(${TARGET} PRIVATE /EHsc)\n  target_compile_definitions(${TARGET} PRIVATE \"_HAS_EXCEPTIONS=0\")\n  target_compile_definitions(${TARGET} PRIVATE \"$<$<CONFIG:Debug>:_DEBUG>\")\nendfunction()\n\n# Flutter library and tool build rules.\nset(FLUTTER_MANAGED_DIR \"${CMAKE_CURRENT_SOURCE_DIR}/flutter\")\nadd_subdirectory(${FLUTTER_MANAGED_DIR})\n\n# Application build; see runner/CMakeLists.txt.\nadd_subdirectory(\"runner\")\n\n\n# Generated plugin build rules, which manage building the plugins and adding\n# them to the application.\ninclude(flutter/generated_plugins.cmake)\n\n\n# === Installation ===\n# Support files are copied into place next to the executable, so that it can\n# run in place. This is done instead of making a separate bundle (as on Linux)\n# so that building and running from within Visual Studio will work.\nset(BUILD_BUNDLE_DIR \"$<TARGET_FILE_DIR:${BINARY_NAME}>\")\n# Make the \"install\" step default, as it's required to run.\nset(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)\nif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)\n  set(CMAKE_INSTALL_PREFIX \"${BUILD_BUNDLE_DIR}\" CACHE PATH \"...\" FORCE)\nendif()\n\nset(INSTALL_BUNDLE_DATA_DIR \"${CMAKE_INSTALL_PREFIX}/data\")\nset(INSTALL_BUNDLE_LIB_DIR \"${CMAKE_INSTALL_PREFIX}\")\n\ninstall(TARGETS ${BINARY_NAME} RUNTIME DESTINATION \"${CMAKE_INSTALL_PREFIX}\"\n  COMPONENT Runtime)\n\ninstall(FILES \"${FLUTTER_ICU_DATA_FILE}\" DESTINATION \"${INSTALL_BUNDLE_DATA_DIR}\"\n  COMPONENT Runtime)\n\ninstall(FILES \"${FLUTTER_LIBRARY}\" DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\n  COMPONENT Runtime)\n\n# install(FILES \"../hiddify-core/bin/hiddify-core.dll\" DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\n#  COMPONENT Runtime)\n\ninstall(FILES \"../hiddify-core/bin/hiddify-core.dll\" DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\nCOMPONENT Runtime RENAME hiddify-core.dll)\n\ninstall(FILES \"../hiddify-core/bin/libcronet.dll\" DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\nCOMPONENT Runtime RENAME libcronet.dll)\n\ninstall(FILES \"../hiddify-core/bin/HiddifyCli.exe\" DESTINATION \"${CMAKE_INSTALL_PREFIX}\"\nCOMPONENT Runtime RENAME HiddifyCli.exe)\n\n\nif(PLUGIN_BUNDLED_LIBRARIES)\n  install(FILES \"${PLUGIN_BUNDLED_LIBRARIES}\"\n    DESTINATION \"${INSTALL_BUNDLE_LIB_DIR}\"\n    COMPONENT Runtime)\nendif()\n\n# Fully re-copy the assets directory on each build to avoid having stale files\n# from a previous install.\nset(FLUTTER_ASSET_DIR_NAME \"flutter_assets\")\ninstall(CODE \"\n  file(REMOVE_RECURSE \\\"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\\\")\n  \" COMPONENT Runtime)\ninstall(DIRECTORY \"${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}\"\n  DESTINATION \"${INSTALL_BUNDLE_DATA_DIR}\" COMPONENT Runtime)\n\n# Install the AOT library on non-Debug builds only.\ninstall(FILES \"${AOT_LIBRARY}\" DESTINATION \"${INSTALL_BUNDLE_DATA_DIR}\"\n  CONFIGURATIONS Profile;Release\n  COMPONENT Runtime)\n"
  },
  {
    "path": "windows/flutter/CMakeLists.txt",
    "content": "# This file controls Flutter-level build steps. It should not be edited.\ncmake_minimum_required(VERSION 3.14)\n\nset(EPHEMERAL_DIR \"${CMAKE_CURRENT_SOURCE_DIR}/ephemeral\")\n\n# Configuration provided via flutter tool.\ninclude(${EPHEMERAL_DIR}/generated_config.cmake)\n\n# TODO: Move the rest of this into files in ephemeral. See\n# https://github.com/flutter/flutter/issues/57146.\nset(WRAPPER_ROOT \"${EPHEMERAL_DIR}/cpp_client_wrapper\")\n\n# Set fallback configurations for older versions of the flutter tool.\nif (NOT DEFINED FLUTTER_TARGET_PLATFORM)\n  set(FLUTTER_TARGET_PLATFORM \"windows-x64\")\nendif()\n\n# === Flutter Library ===\nset(FLUTTER_LIBRARY \"${EPHEMERAL_DIR}/flutter_windows.dll\")\n\n# Published to parent scope for install step.\nset(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)\nset(FLUTTER_ICU_DATA_FILE \"${EPHEMERAL_DIR}/icudtl.dat\" PARENT_SCOPE)\nset(PROJECT_BUILD_DIR \"${PROJECT_DIR}/build/\" PARENT_SCOPE)\nset(AOT_LIBRARY \"${PROJECT_DIR}/build/windows/app.so\" PARENT_SCOPE)\n\nlist(APPEND FLUTTER_LIBRARY_HEADERS\n  \"flutter_export.h\"\n  \"flutter_windows.h\"\n  \"flutter_messenger.h\"\n  \"flutter_plugin_registrar.h\"\n  \"flutter_texture_registrar.h\"\n)\nlist(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND \"${EPHEMERAL_DIR}/\")\nadd_library(flutter INTERFACE)\ntarget_include_directories(flutter INTERFACE\n  \"${EPHEMERAL_DIR}\"\n)\ntarget_link_libraries(flutter INTERFACE \"${FLUTTER_LIBRARY}.lib\")\nadd_dependencies(flutter flutter_assemble)\n\n# === Wrapper ===\nlist(APPEND CPP_WRAPPER_SOURCES_CORE\n  \"core_implementations.cc\"\n  \"standard_codec.cc\"\n)\nlist(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND \"${WRAPPER_ROOT}/\")\nlist(APPEND CPP_WRAPPER_SOURCES_PLUGIN\n  \"plugin_registrar.cc\"\n)\nlist(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND \"${WRAPPER_ROOT}/\")\nlist(APPEND CPP_WRAPPER_SOURCES_APP\n  \"flutter_engine.cc\"\n  \"flutter_view_controller.cc\"\n)\nlist(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND \"${WRAPPER_ROOT}/\")\n\n# Wrapper sources needed for a plugin.\nadd_library(flutter_wrapper_plugin STATIC\n  ${CPP_WRAPPER_SOURCES_CORE}\n  ${CPP_WRAPPER_SOURCES_PLUGIN}\n)\napply_standard_settings(flutter_wrapper_plugin)\nset_target_properties(flutter_wrapper_plugin PROPERTIES\n  POSITION_INDEPENDENT_CODE ON)\nset_target_properties(flutter_wrapper_plugin PROPERTIES\n  CXX_VISIBILITY_PRESET hidden)\ntarget_link_libraries(flutter_wrapper_plugin PUBLIC flutter)\ntarget_include_directories(flutter_wrapper_plugin PUBLIC\n  \"${WRAPPER_ROOT}/include\"\n)\nadd_dependencies(flutter_wrapper_plugin flutter_assemble)\n\n# Wrapper sources needed for the runner.\nadd_library(flutter_wrapper_app STATIC\n  ${CPP_WRAPPER_SOURCES_CORE}\n  ${CPP_WRAPPER_SOURCES_APP}\n)\napply_standard_settings(flutter_wrapper_app)\ntarget_link_libraries(flutter_wrapper_app PUBLIC flutter)\ntarget_include_directories(flutter_wrapper_app PUBLIC\n  \"${WRAPPER_ROOT}/include\"\n)\nadd_dependencies(flutter_wrapper_app flutter_assemble)\n\n# === Flutter tool backend ===\n# _phony_ is a non-existent file to force this command to run every time,\n# since currently there's no way to get a full input/output list from the\n# flutter tool.\nset(PHONY_OUTPUT \"${CMAKE_CURRENT_BINARY_DIR}/_phony_\")\nset_source_files_properties(\"${PHONY_OUTPUT}\" PROPERTIES SYMBOLIC TRUE)\nadd_custom_command(\n  OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}\n    ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}\n    ${CPP_WRAPPER_SOURCES_APP}\n    ${PHONY_OUTPUT}\n  COMMAND ${CMAKE_COMMAND} -E env\n    ${FLUTTER_TOOL_ENVIRONMENT}\n    \"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat\"\n      ${FLUTTER_TARGET_PLATFORM} $<CONFIG>\n  VERBATIM\n)\nadd_custom_target(flutter_assemble DEPENDS\n  \"${FLUTTER_LIBRARY}\"\n  ${FLUTTER_LIBRARY_HEADERS}\n  ${CPP_WRAPPER_SOURCES_CORE}\n  ${CPP_WRAPPER_SOURCES_PLUGIN}\n  ${CPP_WRAPPER_SOURCES_APP}\n)\n"
  },
  {
    "path": "windows/flutter/generated_plugin_registrant.cc",
    "content": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#include \"generated_plugin_registrant.h\"\n\n#include <app_links/app_links_plugin_c_api.h>\n#include <dynamic_color/dynamic_color_plugin_c_api.h>\n#include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.h>\n#include <sentry_flutter/sentry_flutter_plugin.h>\n#include <share_plus/share_plus_windows_plugin_c_api.h>\n#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>\n#include <tray_manager/tray_manager_plugin.h>\n#include <url_launcher_windows/url_launcher_windows.h>\n#include <vclibs/vclibs_plugin_c_api.h>\n#include <window_manager/window_manager_plugin.h>\n\nvoid RegisterPlugins(flutter::PluginRegistry* registry) {\n  AppLinksPluginCApiRegisterWithRegistrar(\n      registry->GetRegistrarForPlugin(\"AppLinksPluginCApi\"));\n  DynamicColorPluginCApiRegisterWithRegistrar(\n      registry->GetRegistrarForPlugin(\"DynamicColorPluginCApi\"));\n  ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(\n      registry->GetRegistrarForPlugin(\"ScreenRetrieverWindowsPluginCApi\"));\n  SentryFlutterPluginRegisterWithRegistrar(\n      registry->GetRegistrarForPlugin(\"SentryFlutterPlugin\"));\n  SharePlusWindowsPluginCApiRegisterWithRegistrar(\n      registry->GetRegistrarForPlugin(\"SharePlusWindowsPluginCApi\"));\n  Sqlite3FlutterLibsPluginRegisterWithRegistrar(\n      registry->GetRegistrarForPlugin(\"Sqlite3FlutterLibsPlugin\"));\n  TrayManagerPluginRegisterWithRegistrar(\n      registry->GetRegistrarForPlugin(\"TrayManagerPlugin\"));\n  UrlLauncherWindowsRegisterWithRegistrar(\n      registry->GetRegistrarForPlugin(\"UrlLauncherWindows\"));\n  VclibsPluginCApiRegisterWithRegistrar(\n      registry->GetRegistrarForPlugin(\"VclibsPluginCApi\"));\n  WindowManagerPluginRegisterWithRegistrar(\n      registry->GetRegistrarForPlugin(\"WindowManagerPlugin\"));\n}\n"
  },
  {
    "path": "windows/flutter/generated_plugin_registrant.h",
    "content": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#ifndef GENERATED_PLUGIN_REGISTRANT_\n#define GENERATED_PLUGIN_REGISTRANT_\n\n#include <flutter/plugin_registry.h>\n\n// Registers Flutter plugins.\nvoid RegisterPlugins(flutter::PluginRegistry* registry);\n\n#endif  // GENERATED_PLUGIN_REGISTRANT_\n"
  },
  {
    "path": "windows/flutter/generated_plugins.cmake",
    "content": "#\n# Generated file, do not edit.\n#\n\nlist(APPEND FLUTTER_PLUGIN_LIST\n  app_links\n  dynamic_color\n  screen_retriever_windows\n  sentry_flutter\n  share_plus\n  sqlite3_flutter_libs\n  tray_manager\n  url_launcher_windows\n  vclibs\n  window_manager\n)\n\nlist(APPEND FLUTTER_FFI_PLUGIN_LIST\n)\n\nset(PLUGIN_BUNDLED_LIBRARIES)\n\nforeach(plugin ${FLUTTER_PLUGIN_LIST})\n  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})\n  target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)\n  list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)\n  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})\nendforeach(plugin)\n\nforeach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})\n  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})\n  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})\nendforeach(ffi_plugin)\n"
  },
  {
    "path": "windows/packaging/exe/inno_setup.sas",
    "content": "[Setup]\nAppId={{APP_ID}}\nAppVersion={{APP_VERSION}}\nAppName={{DISPLAY_NAME}}\nAppPublisher={{PUBLISHER_NAME}}\nAppPublisherURL={{PUBLISHER_URL}}\nAppSupportURL={{PUBLISHER_URL}}\nAppUpdatesURL={{PUBLISHER_URL}}\nDefaultDirName={{INSTALL_DIR_NAME}}\nDisableProgramGroupPage=yes\nOutputDir=.\nOutputBaseFilename={{OUTPUT_BASE_FILENAME}}\nCompression=lzma\nSolidCompression=yes\nSetupIconFile={{SETUP_ICON_FILE}}\nWizardStyle=modern\nPrivilegesRequired={{PRIVILEGES_REQUIRED}}\nArchitecturesAllowed=x64\nArchitecturesInstallIn64BitMode=x64\nCloseApplications=force\n\n[Languages]\n{% for locale in LOCALES %}\n{% if locale == 'en' %}Name: \"english\"; MessagesFile: \"compiler:Default.isl\"{% endif %}\n{% if locale == 'hy' %}Name: \"armenian\"; MessagesFile: \"compiler:Languages\\\\Armenian.isl\"{% endif %}\n{% if locale == 'bg' %}Name: \"bulgarian\"; MessagesFile: \"compiler:Languages\\\\Bulgarian.isl\"{% endif %}\n{% if locale == 'ca' %}Name: \"catalan\"; MessagesFile: \"compiler:Languages\\\\Catalan.isl\"{% endif %}\n{% if locale == 'zh' %}Name: \"chinesesimplified\"; MessagesFile: \"compiler:Languages\\\\ChineseSimplified.isl\"{% endif %}\n{% if locale == 'co' %}Name: \"corsican\"; MessagesFile: \"compiler:Languages\\\\Corsican.isl\"{% endif %}\n{% if locale == 'cs' %}Name: \"czech\"; MessagesFile: \"compiler:Languages\\\\Czech.isl\"{% endif %}\n{% if locale == 'da' %}Name: \"danish\"; MessagesFile: \"compiler:Languages\\\\Danish.isl\"{% endif %}\n{% if locale == 'nl' %}Name: \"dutch\"; MessagesFile: \"compiler:Languages\\\\Dutch.isl\"{% endif %}\n{% if locale == 'fi' %}Name: \"finnish\"; MessagesFile: \"compiler:Languages\\\\Finnish.isl\"{% endif %}\n{% if locale == 'fr' %}Name: \"french\"; MessagesFile: \"compiler:Languages\\\\French.isl\"{% endif %}\n{% if locale == 'de' %}Name: \"german\"; MessagesFile: \"compiler:Languages\\\\German.isl\"{% endif %}\n{% if locale == 'he' %}Name: \"hebrew\"; MessagesFile: \"compiler:Languages\\\\Hebrew.isl\"{% endif %}\n{% if locale == 'is' %}Name: \"icelandic\"; MessagesFile: \"compiler:Languages\\\\Icelandic.isl\"{% endif %}\n{% if locale == 'it' %}Name: \"italian\"; MessagesFile: \"compiler:Languages\\\\Italian.isl\"{% endif %}\n{% if locale == 'ja' %}Name: \"japanese\"; MessagesFile: \"compiler:Languages\\\\Japanese.isl\"{% endif %}\n{% if locale == 'no' %}Name: \"norwegian\"; MessagesFile: \"compiler:Languages\\\\Norwegian.isl\"{% endif %}\n{% if locale == 'pl' %}Name: \"polish\"; MessagesFile: \"compiler:Languages\\\\Polish.isl\"{% endif %}\n{% if locale == 'pt' %}Name: \"portuguese\"; MessagesFile: \"compiler:Languages\\\\Portuguese.isl\"{% endif %}\n{% if locale == 'ru' %}Name: \"russian\"; MessagesFile: \"compiler:Languages\\\\Russian.isl\"{% endif %}\n{% if locale == 'sk' %}Name: \"slovak\"; MessagesFile: \"compiler:Languages\\\\Slovak.isl\"{% endif %}\n{% if locale == 'sl' %}Name: \"slovenian\"; MessagesFile: \"compiler:Languages\\\\Slovenian.isl\"{% endif %}\n{% if locale == 'es' %}Name: \"spanish\"; MessagesFile: \"compiler:Languages\\\\Spanish.isl\"{% endif %}\n{% if locale == 'tr' %}Name: \"turkish\"; MessagesFile: \"compiler:Languages\\\\Turkish.isl\"{% endif %}\n{% if locale == 'uk' %}Name: \"ukrainian\"; MessagesFile: \"compiler:Languages\\\\Ukrainian.isl\"{% endif %}\n{% endfor %}\n\n[Tasks]\nName: \"desktopicon\"; Description: \"{cm:CreateDesktopIcon}\"; GroupDescription: \"{cm:AdditionalIcons}\"; Flags: {% if CREATE_DESKTOP_ICON != true %}unchecked{% else %}checkedonce{% endif %}\nName: \"launchAtStartup\"; Description: \"{cm:AutoStartProgram,{{DISPLAY_NAME}}}\"; GroupDescription: \"{cm:AdditionalIcons}\"; Flags: {% if LAUNCH_AT_STARTUP != true %}unchecked{% else %}checkedonce{% endif %}\n[Files]\nSource: \"{{SOURCE_DIR}}\\\\*\"; DestDir: \"{app}\"; Flags: ignoreversion recursesubdirs createallsubdirs\n; NOTE: Don't use \"Flags: ignoreversion\" on any shared system files\n\n[Icons]\nName: \"{autoprograms}\\\\{{DISPLAY_NAME}}\"; Filename: \"{app}\\\\{{EXECUTABLE_NAME}}\"\nName: \"{autodesktop}\\\\{{DISPLAY_NAME}}\"; Filename: \"{app}\\\\{{EXECUTABLE_NAME}}\"; Tasks: desktopicon\nName: \"{userstartup}\\\\{{DISPLAY_NAME}}\"; Filename: \"{app}\\\\{{EXECUTABLE_NAME}}\"; WorkingDir: \"{app}\"; Tasks: launchAtStartup\n[Run]\nFilename: \"{app}\\\\{{EXECUTABLE_NAME}}\"; Description: \"{cm:LaunchProgram,{{DISPLAY_NAME}}}\"; Flags: {% if PRIVILEGES_REQUIRED == 'admin' %}runascurrentuser{% endif %} nowait postinstall skipifsilent\n\n[UninstallDelete]\nType: filesandordirs; Name: \"{userappdata}\\Hiddify\"\n\n[Code]\nfunction InitializeSetup(): Boolean;\nvar\n  ResultCode: Integer;\nbegin\n  Exec('taskkill', '/F /IM hiddify.exe', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)\n  Exec('net', 'stop \"HiddifyTunnelService\"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)\n  Exec('sc.exe', 'delete \"HiddifyTunnelService\"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)\n  Result := True;\nend;"
  },
  {
    "path": "windows/packaging/exe/make_config.yaml",
    "content": "app_id: 6L903538-42B1-4596-G479-BJ779F21A65D\npublisher: Hiddify\npublisher_url: https://github.com/hiddify/hiddify-app\ndisplay_name: Hiddify\ncreate_desktop_icon: true\ninstall_dir_name: \"{autopf64}\\\\Hiddify\"\nsetup_icon_file: windows\\runner\\resources\\app_icon.ico\nlocales:\n  - ar\n  - en\n  - es\n  - fr\n  - pt\n  - ru\n  - tr\nscript_template: inno_setup.sas\n"
  },
  {
    "path": "windows/packaging/msix/make_config.yaml",
    "content": "display_name: Hiddify\r\npublisher_display_name: Hiddify\r\nidentity_name: Hiddify.HiddifyNext\r\nmsix_version: 4.1.2.0\nlogo_path: windows\\runner\\resources\\app_icon.ico\r\ncapabilities: internetClient, internetClientServer, privateNetworkClientServer\r\nlanguages: ar, en-us, es-es, fa-ir, fr-fr, id-id, pt-br, ru-ru, tr-tr, zh-cn, zh-tw\r\nprotocol_activation: hiddify, v2ray, v2rayn, v2rayng, clash, clashmeta, sing-box\r\nexecution_alias: hiddify\r\ncertificate_path: windows\\sign.pfx\r\ncertificate_password:\r\npublisher: CN=8CB43675-F44B-4AA5-9372-E8727781BDC4\r\ninstall_certificate: \"false\"\r\nenable_at_startup: \"true\"\r\nstartup_task:\r\n  parameters: --autostart\r\n\r\n# For testing with a self-signed certificate\r\n# publisher: CN=Hiddify-Test\r\n# certificate_password: \"1234\"\r\n# install_certificate: \"true\""
  },
  {
    "path": "windows/runner/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.14)\nproject(runner LANGUAGES CXX)\n\n# Define the application target. To change its name, change BINARY_NAME in the\n# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer\n# work.\n#\n# Any new source files that you add to the application should be added here.\nadd_executable(${BINARY_NAME} WIN32\n  \"flutter_window.cpp\"\n  \"main.cpp\"\n  \"utils.cpp\"\n  \"win32_window.cpp\"\n  \"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc\"\n  \"Runner.rc\"\n  \"runner.exe.manifest\"\n)\n\n# Apply the standard set of build settings. This can be removed for applications\n# that need different build settings.\napply_standard_settings(${BINARY_NAME})\n\n# Add preprocessor definitions for the build version.\ntarget_compile_definitions(${BINARY_NAME} PRIVATE \"FLUTTER_VERSION=\\\"${FLUTTER_VERSION}\\\"\")\ntarget_compile_definitions(${BINARY_NAME} PRIVATE \"FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}\")\ntarget_compile_definitions(${BINARY_NAME} PRIVATE \"FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}\")\ntarget_compile_definitions(${BINARY_NAME} PRIVATE \"FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}\")\ntarget_compile_definitions(${BINARY_NAME} PRIVATE \"FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}\")\n\n# Disable Windows macros that collide with C++ standard library functions.\ntarget_compile_definitions(${BINARY_NAME} PRIVATE \"NOMINMAX\")\n\n# Add dependency libraries and include directories. Add any application-specific\n# dependencies here.\ntarget_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)\ntarget_link_libraries(${BINARY_NAME} PRIVATE \"dwmapi.lib\")\ntarget_include_directories(${BINARY_NAME} PRIVATE \"${CMAKE_SOURCE_DIR}\")\n\n# Run the Flutter tool portions of the build. This must not be removed.\nadd_dependencies(${BINARY_NAME} flutter_assemble)\n"
  },
  {
    "path": "windows/runner/Runner.rc",
    "content": "// Microsoft Visual C++ generated resource script.\n//\n#pragma code_page(65001)\n#include \"resource.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"winres.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// English (United States) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE\nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE\nBEGIN\n    \"#include \"\"winres.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE\nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Icon\n//\n\n// Icon with lowest ID value placed first to ensure application icon\n// remains consistent on all systems.\nIDI_APP_ICON            ICON                    \"resources\\\\app_icon.ico\"\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\n#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)\n#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD\n#else\n#define VERSION_AS_NUMBER 1,0,0,0\n#endif\n\n#if defined(FLUTTER_VERSION)\n#define VERSION_AS_STRING FLUTTER_VERSION\n#else\n#define VERSION_AS_STRING \"1.0.0\"\n#endif\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION VERSION_AS_NUMBER\n PRODUCTVERSION VERSION_AS_NUMBER\n FILEFLAGSMASK VS_FFI_FILEFLAGSMASK\n#ifdef _DEBUG\n FILEFLAGS VS_FF_DEBUG\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS VOS__WINDOWS32\n FILETYPE VFT_APP\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"040904e4\"\n        BEGIN\n            VALUE \"CompanyName\", \"Hiddify\" \"\\0\"\n            VALUE \"FileDescription\", \"Hiddify\" \"\\0\"\n            VALUE \"FileVersion\", VERSION_AS_STRING \"\\0\"\n            VALUE \"InternalName\", \"hiddify\" \"\\0\"\n            VALUE \"LegalCopyright\", \"Copyright (C) 2023 Hiddify.com. All rights reserved.\" \"\\0\"\n            VALUE \"OriginalFilename\", \"Hiddify.exe\" \"\\0\"\n            VALUE \"ProductName\", \"hiddify\" \"\\0\"\n            VALUE \"ProductVersion\", VERSION_AS_STRING \"\\0\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x409, 1252\n    END\nEND\n\n#endif    // English (United States) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n"
  },
  {
    "path": "windows/runner/flutter_window.cpp",
    "content": "#include \"flutter_window.h\"\n\n#include <optional>\n\n#include \"flutter/generated_plugin_registrant.h\"\n\nFlutterWindow::FlutterWindow(const flutter::DartProject& project)\n    : project_(project) {}\n\nFlutterWindow::~FlutterWindow() {}\n\nbool FlutterWindow::OnCreate() {\n  if (!Win32Window::OnCreate()) {\n    return false;\n  }\n\n  RECT frame = GetClientArea();\n\n  // The size here must match the window dimensions to avoid unnecessary surface\n  // creation / destruction in the startup path.\n  flutter_controller_ = std::make_unique<flutter::FlutterViewController>(\n      frame.right - frame.left, frame.bottom - frame.top, project_);\n  // Ensure that basic setup of the controller was successful.\n  if (!flutter_controller_->engine() || !flutter_controller_->view()) {\n    return false;\n  }\n  RegisterPlugins(flutter_controller_->engine());\n  SetChildContent(flutter_controller_->view()->GetNativeWindow());\n\n  flutter_controller_->engine()->SetNextFrameCallback([&]() {\n    // this->Show(); window_manager hidden at launch\n    \"\";\n  });\n\n  // Flutter can complete the first frame before the \"show window\" callback is\n  // registered. The following call ensures a frame is pending to ensure the\n  // window is shown. It is a no-op if the first frame hasn't completed yet.\n  flutter_controller_->ForceRedraw();\n\n  return true;\n}\n\nvoid FlutterWindow::OnDestroy() {\n  if (flutter_controller_) {\n    flutter_controller_ = nullptr;\n  }\n\n  Win32Window::OnDestroy();\n}\n\nLRESULT\nFlutterWindow::MessageHandler(HWND hwnd, UINT const message,\n                              WPARAM const wparam,\n                              LPARAM const lparam) noexcept {\n  // Give Flutter, including plugins, an opportunity to handle window messages.\n  if (flutter_controller_) {\n    std::optional<LRESULT> result =\n        flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,\n                                                      lparam);\n    if (result) {\n      return *result;\n    }\n  }\n\n  switch (message) {\n    case WM_FONTCHANGE:\n      flutter_controller_->engine()->ReloadSystemFonts();\n      break;\n  }\n\n  return Win32Window::MessageHandler(hwnd, message, wparam, lparam);\n}\n"
  },
  {
    "path": "windows/runner/flutter_window.h",
    "content": "#ifndef RUNNER_FLUTTER_WINDOW_H_\n#define RUNNER_FLUTTER_WINDOW_H_\n\n#include <flutter/dart_project.h>\n#include <flutter/flutter_view_controller.h>\n\n#include <memory>\n\n#include \"win32_window.h\"\n\n// A window that does nothing but host a Flutter view.\nclass FlutterWindow : public Win32Window {\n public:\n  // Creates a new FlutterWindow hosting a Flutter view running |project|.\n  explicit FlutterWindow(const flutter::DartProject& project);\n  virtual ~FlutterWindow();\n\n protected:\n  // Win32Window:\n  bool OnCreate() override;\n  void OnDestroy() override;\n  LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,\n                         LPARAM const lparam) noexcept override;\n\n private:\n  // The project to run.\n  flutter::DartProject project_;\n\n  // The Flutter instance hosted by this window.\n  std::unique_ptr<flutter::FlutterViewController> flutter_controller_;\n};\n\n#endif  // RUNNER_FLUTTER_WINDOW_H_\n"
  },
  {
    "path": "windows/runner/main.cpp",
    "content": "#include <flutter/dart_project.h>\n#include <flutter/flutter_view_controller.h>\n#include <windows.h>\n\n#include \"flutter_window.h\"\n#include \"utils.h\"\n#include \"app_links/app_links_plugin_c_api.h\"\n// #include <protocol_handler_windows/protocol_handler_windows_plugin_c_api.h>\n\nbool SendAppLinkToInstance(const std::wstring &title)\n{\n  // Find our exact window\n  HWND hwnd = ::FindWindow(L\"FLUTTER_RUNNER_WIN32_WINDOW\", title.c_str());\n\n  if (hwnd)\n  {\n    // Dispatch new link to current window\n    SendAppLink(hwnd);\n\n    // (Optional) Restore our window to front in same state\n    WINDOWPLACEMENT place = {sizeof(WINDOWPLACEMENT)};\n    GetWindowPlacement(hwnd, &place);\n\n    switch (place.showCmd)\n    {\n    case SW_SHOWMAXIMIZED:\n      ShowWindow(hwnd, SW_SHOWMAXIMIZED);\n      break;\n    case SW_SHOWMINIMIZED:\n      ShowWindow(hwnd, SW_RESTORE);\n      break;\n    default:\n      ShowWindow(hwnd, SW_NORMAL);\n      break;\n    }\n\n    SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);\n    SetForegroundWindow(hwnd);\n    // END (Optional) Restore\n\n    // Window has been found, don't create another one.\n    return true;\n  }\n\n  return false;\n}\n\nint APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,\n                      _In_ wchar_t *command_line, _In_ int show_command)\n{\n\n  // Replace \"example\" with the generated title found as parameter of `window.Create` in this file.\n  // You may ignore the result if you need to create another window.\n  if (SendAppLinkToInstance(L\"Hiddify\"))\n  {\n    return EXIT_SUCCESS;\n  }\n\n  HANDLE hMutexInstance = CreateMutex(NULL, TRUE, L\"HiddifyMutex\");\n  HWND handle = FindWindowA(NULL, \"Hiddify\");\n\n  if (GetLastError() == ERROR_ALREADY_EXISTS)\n  {\n    flutter::DartProject project(L\"data\");\n    std::vector<std::string> command_line_arguments = GetCommandLineArguments();\n    project.set_dart_entrypoint_arguments(std::move(command_line_arguments));\n    FlutterWindow window(project);\n    if (window.SendAppLinkToInstance(L\"Hiddify\"))\n    {\n      return false;\n    }\n\n    WINDOWPLACEMENT place = {sizeof(WINDOWPLACEMENT)};\n    GetWindowPlacement(handle, &place);\n    ShowWindow(handle, SW_NORMAL);\n    return 0;\n  }\n\n  // Attach to console when present (e.g., 'flutter run') or create a\n  // new console when running with a debugger.\n  if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent())\n  {\n    CreateAndAttachConsole();\n  }\n\n  // Initialize COM, so that it is available for use in the library and/or\n  // plugins.\n  ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);\n\n  flutter::DartProject project(L\"data\");\n\n  std::vector<std::string> command_line_arguments =\n      GetCommandLineArguments();\n\n  project.set_dart_entrypoint_arguments(std::move(command_line_arguments));\n\n  FlutterWindow window(project);\n  Win32Window::Point origin(10, 10);\n  Win32Window::Size size(1280, 720);\n  if (!window.Create(L\"Hiddify\", origin, size))\n  {\n    return EXIT_FAILURE;\n  }\n  window.SetQuitOnClose(true);\n\n  ::MSG msg;\n  while (::GetMessage(&msg, nullptr, 0, 0))\n  {\n    ::TranslateMessage(&msg);\n    ::DispatchMessage(&msg);\n  }\n\n  ::CoUninitialize();\n  ReleaseMutex(hMutexInstance);\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "windows/runner/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by Runner.rc\n//\n#define IDI_APP_ICON                    101\n\n// Next default values for new objects\n//\n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        102\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1001\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "windows/runner/runner.exe.manifest",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n  <application xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n    <windowsSettings>\n      <dpiAwareness xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">PerMonitorV2</dpiAwareness>\n    </windowsSettings>\n  </application>\n  <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n    <application>\n      <!-- Windows 10 and Windows 11 -->\n      <supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n      <!-- Windows 8.1 -->\n      <supportedOS Id=\"{1f676c76-80e1-4239-95bb-83d0f6d0da78}\"/>\n      <!-- Windows 8 -->\n      <supportedOS Id=\"{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}\"/>\n      <!-- Windows 7 -->\n      <supportedOS Id=\"{35138b9a-5d96-4fbd-8e2d-a2440225f93a}\"/>\n    </application>\n  </compatibility>\n</assembly>\n"
  },
  {
    "path": "windows/runner/utils.cpp",
    "content": "#include \"utils.h\"\n\n#include <flutter_windows.h>\n#include <io.h>\n#include <stdio.h>\n#include <windows.h>\n\n#include <iostream>\n\nvoid CreateAndAttachConsole() {\n  if (::AllocConsole()) {\n    FILE *unused;\n    if (freopen_s(&unused, \"CONOUT$\", \"w\", stdout)) {\n      _dup2(_fileno(stdout), 1);\n    }\n    if (freopen_s(&unused, \"CONOUT$\", \"w\", stderr)) {\n      _dup2(_fileno(stdout), 2);\n    }\n    std::ios::sync_with_stdio();\n    FlutterDesktopResyncOutputStreams();\n  }\n}\n\nstd::vector<std::string> GetCommandLineArguments() {\n  // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.\n  int argc;\n  wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);\n  if (argv == nullptr) {\n    return std::vector<std::string>();\n  }\n\n  std::vector<std::string> command_line_arguments;\n\n  // Skip the first argument as it's the binary name.\n  for (int i = 1; i < argc; i++) {\n    command_line_arguments.push_back(Utf8FromUtf16(argv[i]));\n  }\n\n  ::LocalFree(argv);\n\n  return command_line_arguments;\n}\n\nstd::string Utf8FromUtf16(const wchar_t* utf16_string) {\n  if (utf16_string == nullptr) {\n    return std::string();\n  }\n  int target_length = ::WideCharToMultiByte(\n      CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,\n      -1, nullptr, 0, nullptr, nullptr)\n    -1; // remove the trailing null character\n  int input_length = (int)wcslen(utf16_string);\n  std::string utf8_string;\n  if (target_length <= 0 || target_length > utf8_string.max_size()) {\n    return utf8_string;\n  }\n  utf8_string.resize(target_length);\n  int converted_length = ::WideCharToMultiByte(\n      CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,\n      input_length, utf8_string.data(), target_length, nullptr, nullptr);\n  if (converted_length == 0) {\n    return std::string();\n  }\n  return utf8_string;\n}\n"
  },
  {
    "path": "windows/runner/utils.h",
    "content": "#ifndef RUNNER_UTILS_H_\n#define RUNNER_UTILS_H_\n\n#include <string>\n#include <vector>\n\n// Creates a console for the process, and redirects stdout and stderr to\n// it for both the runner and the Flutter library.\nvoid CreateAndAttachConsole();\n\n// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string\n// encoded in UTF-8. Returns an empty std::string on failure.\nstd::string Utf8FromUtf16(const wchar_t* utf16_string);\n\n// Gets the command line arguments passed in as a std::vector<std::string>,\n// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.\nstd::vector<std::string> GetCommandLineArguments();\n\n#endif  // RUNNER_UTILS_H_\n"
  },
  {
    "path": "windows/runner/win32_window.cpp",
    "content": "#include \"win32_window.h\"\n\n#include <dwmapi.h>\n#include <flutter_windows.h>\n\n#include \"resource.h\"\n// #include <protocol_handler_windows/protocol_handler_windows_plugin_c_api.h>\n\nnamespace\n{\n\n/// Window attribute that enables dark mode window decorations.\n///\n/// Redefined in case the developer's machine has a Windows SDK older than\n/// version 10.0.22000.0.\n/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute\n#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE\n#define DWMWA_USE_IMMERSIVE_DARK_MODE 20\n#endif\n\n  constexpr const wchar_t kWindowClassName[] = L\"FLUTTER_RUNNER_WIN32_WINDOW\";\n\n  /// Registry key for app theme preference.\n  ///\n  /// A value of 0 indicates apps should use dark mode. A non-zero or missing\n  /// value indicates apps should use light mode.\n  constexpr const wchar_t kGetPreferredBrightnessRegKey[] =\n      L\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Themes\\\\Personalize\";\n  constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L\"AppsUseLightTheme\";\n\n  // The number of Win32Window objects that currently exist.\n  static int g_active_window_count = 0;\n\n  using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);\n\n  // Scale helper to convert logical scaler values to physical using passed in\n  // scale factor\n  int Scale(int source, double scale_factor)\n  {\n    return static_cast<int>(source * scale_factor);\n  }\n\n  // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.\n  // This API is only needed for PerMonitor V1 awareness mode.\n  void EnableFullDpiSupportIfAvailable(HWND hwnd)\n  {\n    HMODULE user32_module = LoadLibraryA(\"User32.dll\");\n    if (!user32_module)\n    {\n      return;\n    }\n    auto enable_non_client_dpi_scaling =\n        reinterpret_cast<EnableNonClientDpiScaling *>(\n            GetProcAddress(user32_module, \"EnableNonClientDpiScaling\"));\n    if (enable_non_client_dpi_scaling != nullptr)\n    {\n      enable_non_client_dpi_scaling(hwnd);\n    }\n    FreeLibrary(user32_module);\n  }\n\n} // namespace\n\n// Manages the Win32Window's window class registration.\nclass WindowClassRegistrar\n{\npublic:\n  ~WindowClassRegistrar() = default;\n\n  // Returns the singleton registrar instance.\n  static WindowClassRegistrar *GetInstance()\n  {\n    if (!instance_)\n    {\n      instance_ = new WindowClassRegistrar();\n    }\n    return instance_;\n  }\n\n  // Returns the name of the window class, registering the class if it hasn't\n  // previously been registered.\n  const wchar_t *GetWindowClass();\n\n  // Unregisters the window class. Should only be called if there are no\n  // instances of the window.\n  void UnregisterWindowClass();\n\nprivate:\n  WindowClassRegistrar() = default;\n\n  static WindowClassRegistrar *instance_;\n\n  bool class_registered_ = false;\n};\n\nWindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr;\n\nconst wchar_t *WindowClassRegistrar::GetWindowClass()\n{\n  if (!class_registered_)\n  {\n    WNDCLASS window_class{};\n    window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);\n    window_class.lpszClassName = kWindowClassName;\n    window_class.style = CS_HREDRAW | CS_VREDRAW;\n    window_class.cbClsExtra = 0;\n    window_class.cbWndExtra = 0;\n    window_class.hInstance = GetModuleHandle(nullptr);\n    window_class.hIcon =\n        LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));\n    window_class.hbrBackground = 0;\n    window_class.lpszMenuName = nullptr;\n    window_class.lpfnWndProc = Win32Window::WndProc;\n    RegisterClass(&window_class);\n    class_registered_ = true;\n  }\n  return kWindowClassName;\n}\n\nvoid WindowClassRegistrar::UnregisterWindowClass()\n{\n  UnregisterClass(kWindowClassName, nullptr);\n  class_registered_ = false;\n}\n\nWin32Window::Win32Window()\n{\n  ++g_active_window_count;\n}\n\nWin32Window::~Win32Window()\n{\n  --g_active_window_count;\n  Destroy();\n}\n\nbool Win32Window::Create(const std::wstring &title,\n                         const Point &origin,\n                         const Size &size)\n{\n  if (SendAppLinkToInstance(title))\n  {\n    return false;\n  }\n\n  Destroy();\n\n  const wchar_t *window_class =\n      WindowClassRegistrar::GetInstance()->GetWindowClass();\n\n  const POINT target_point = {static_cast<LONG>(origin.x),\n                              static_cast<LONG>(origin.y)};\n  HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);\n  UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);\n  double scale_factor = dpi / 96.0;\n\n  HWND window = CreateWindow(\n      // window_class, title.c_str(), WS_OVERLAPPEDWINDOW, // window_manager hidden at launch\n      window_class, title.c_str(),\n      WS_OVERLAPPEDWINDOW, // do not add WS_VISIBLE since the window will be shown later\n      Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),\n      Scale(size.width, scale_factor), Scale(size.height, scale_factor),\n      nullptr, nullptr, GetModuleHandle(nullptr), this);\n\n  if (!window)\n  {\n    return false;\n  }\n\n  UpdateTheme(window);\n\n  return OnCreate();\n}\n\nbool Win32Window::Show()\n{\n  return ShowWindow(window_handle_, SW_SHOWNORMAL);\n}\n\nbool Win32Window::SendAppLinkToInstance(const std::wstring &title)\n{\n  // Find our exact window\n  HWND hwnd = ::FindWindow(kWindowClassName, title.c_str());\n\n  if (hwnd)\n  {\n    // Dispatch new link to current window\n    // DispatchToProtocolHandler(hwnd);\n\n    // (Optional) Restore our window to front in same state\n    WINDOWPLACEMENT place = {sizeof(WINDOWPLACEMENT)};\n    GetWindowPlacement(hwnd, &place);\n\n    switch (place.showCmd)\n    {\n    case SW_SHOWMAXIMIZED:\n      ShowWindow(hwnd, SW_SHOWMAXIMIZED);\n      break;\n    case SW_SHOWMINIMIZED:\n      ShowWindow(hwnd, SW_RESTORE);\n      break;\n    default:\n      ShowWindow(hwnd, SW_NORMAL);\n      break;\n    }\n\n    SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);\n    SetForegroundWindow(hwnd);\n\n    // Window has been found, don't create another one.\n    return true;\n  }\n\n  return false;\n}\n\n// static\nLRESULT CALLBACK Win32Window::WndProc(HWND const window,\n                                      UINT const message,\n                                      WPARAM const wparam,\n                                      LPARAM const lparam) noexcept\n{\n  if (message == WM_NCCREATE)\n  {\n    auto window_struct = reinterpret_cast<CREATESTRUCT *>(lparam);\n    SetWindowLongPtr(window, GWLP_USERDATA,\n                     reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));\n\n    auto that = static_cast<Win32Window *>(window_struct->lpCreateParams);\n    EnableFullDpiSupportIfAvailable(window);\n    that->window_handle_ = window;\n  }\n  else if (Win32Window *that = GetThisFromHandle(window))\n  {\n    return that->MessageHandler(window, message, wparam, lparam);\n  }\n\n  return DefWindowProc(window, message, wparam, lparam);\n}\n\nLRESULT\nWin32Window::MessageHandler(HWND hwnd,\n                            UINT const message,\n                            WPARAM const wparam,\n                            LPARAM const lparam) noexcept\n{\n  switch (message)\n  {\n  case WM_DESTROY:\n    window_handle_ = nullptr;\n    Destroy();\n    if (quit_on_close_)\n    {\n      PostQuitMessage(0);\n    }\n    return 0;\n\n  case WM_DPICHANGED:\n  {\n    auto newRectSize = reinterpret_cast<RECT *>(lparam);\n    LONG newWidth = newRectSize->right - newRectSize->left;\n    LONG newHeight = newRectSize->bottom - newRectSize->top;\n\n    SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,\n                 newHeight, SWP_NOZORDER | SWP_NOACTIVATE);\n\n    return 0;\n  }\n  case WM_SIZE:\n  {\n    RECT rect = GetClientArea();\n    if (child_content_ != nullptr)\n    {\n      // Size and position the child window.\n      MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,\n                 rect.bottom - rect.top, TRUE);\n    }\n    return 0;\n  }\n\n  case WM_ACTIVATE:\n    if (child_content_ != nullptr)\n    {\n      SetFocus(child_content_);\n    }\n    return 0;\n\n  case WM_DWMCOLORIZATIONCOLORCHANGED:\n    UpdateTheme(hwnd);\n    return 0;\n  }\n\n  return DefWindowProc(window_handle_, message, wparam, lparam);\n}\n\nvoid Win32Window::Destroy()\n{\n  OnDestroy();\n\n  if (window_handle_)\n  {\n    DestroyWindow(window_handle_);\n    window_handle_ = nullptr;\n  }\n  if (g_active_window_count == 0)\n  {\n    WindowClassRegistrar::GetInstance()->UnregisterWindowClass();\n  }\n}\n\nWin32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept\n{\n  return reinterpret_cast<Win32Window *>(\n      GetWindowLongPtr(window, GWLP_USERDATA));\n}\n\nvoid Win32Window::SetChildContent(HWND content)\n{\n  child_content_ = content;\n  SetParent(content, window_handle_);\n  RECT frame = GetClientArea();\n\n  MoveWindow(content, frame.left, frame.top, frame.right - frame.left,\n             frame.bottom - frame.top, true);\n\n  SetFocus(child_content_);\n}\n\nRECT Win32Window::GetClientArea()\n{\n  RECT frame;\n  GetClientRect(window_handle_, &frame);\n  return frame;\n}\n\nHWND Win32Window::GetHandle()\n{\n  return window_handle_;\n}\n\nvoid Win32Window::SetQuitOnClose(bool quit_on_close)\n{\n  quit_on_close_ = quit_on_close;\n}\n\nbool Win32Window::OnCreate()\n{\n  // No-op; provided for subclasses.\n  return true;\n}\n\nvoid Win32Window::OnDestroy()\n{\n  // No-op; provided for subclasses.\n}\n\nvoid Win32Window::UpdateTheme(HWND const window)\n{\n  DWORD light_mode;\n  DWORD light_mode_size = sizeof(light_mode);\n  LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,\n                               kGetPreferredBrightnessRegValue,\n                               RRF_RT_REG_DWORD, nullptr, &light_mode,\n                               &light_mode_size);\n\n  if (result == ERROR_SUCCESS)\n  {\n    BOOL enable_dark_mode = light_mode == 0;\n    DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,\n                          &enable_dark_mode, sizeof(enable_dark_mode));\n  }\n}\n"
  },
  {
    "path": "windows/runner/win32_window.h",
    "content": "#ifndef RUNNER_WIN32_WINDOW_H_\n#define RUNNER_WIN32_WINDOW_H_\n\n#include <windows.h>\n\n#include <functional>\n#include <memory>\n#include <string>\n// #include <protocol_handler_windows/protocol_handler_windows_plugin_c_api.h>\n// A class abstraction for a high DPI-aware Win32 Window. Intended to be\n// inherited from by classes that wish to specialize with custom\n// rendering and input handling\nclass Win32Window\n{\npublic:\n  struct Point\n  {\n    unsigned int x;\n    unsigned int y;\n    Point(unsigned int x, unsigned int y) : x(x), y(y) {}\n  };\n\n  struct Size\n  {\n    unsigned int width;\n    unsigned int height;\n    Size(unsigned int width, unsigned int height)\n        : width(width), height(height) {}\n  };\n\n  Win32Window();\n  virtual ~Win32Window();\n\n  // Creates a win32 window with |title| that is positioned and sized using\n  // |origin| and |size|. New windows are created on the default monitor. Window\n  // sizes are specified to the OS in physical pixels, hence to ensure a\n  // consistent size this function will scale the inputted width and height as\n  // as appropriate for the default monitor. The window is invisible until\n  // |Show| is called. Returns true if the window was created successfully.\n  bool Create(const std::wstring &title, const Point &origin, const Size &size);\n\n  bool SendAppLinkToInstance(const std::wstring &title);\n\n  // Show the current window. Returns true if the window was successfully shown.\n  bool Show();\n\n  // Release OS resources associated with window.\n  void Destroy();\n\n  // Inserts |content| into the window tree.\n  void SetChildContent(HWND content);\n\n  // Returns the backing Window handle to enable clients to set icon and other\n  // window properties. Returns nullptr if the window has been destroyed.\n  HWND GetHandle();\n\n  // If true, closing this window will quit the application.\n  void SetQuitOnClose(bool quit_on_close);\n\n  // Return a RECT representing the bounds of the current client area.\n  RECT GetClientArea();\n\nprotected:\n  // Processes and route salient window messages for mouse handling,\n  // size change and DPI. Delegates handling of these to member overloads that\n  // inheriting classes can handle.\n  virtual LRESULT MessageHandler(HWND window,\n                                 UINT const message,\n                                 WPARAM const wparam,\n                                 LPARAM const lparam) noexcept;\n\n  // Called when CreateAndShow is called, allowing subclass window-related\n  // setup. Subclasses should return false if setup fails.\n  virtual bool OnCreate();\n\n  // Called when Destroy is called.\n  virtual void OnDestroy();\n\nprivate:\n  friend class WindowClassRegistrar;\n\n  // OS callback called by message pump. Handles the WM_NCCREATE message which\n  // is passed when the non-client area is being created and enables automatic\n  // non-client DPI scaling so that the non-client area automatically\n  // responds to changes in DPI. All other messages are handled by\n  // MessageHandler.\n  static LRESULT CALLBACK WndProc(HWND const window,\n                                  UINT const message,\n                                  WPARAM const wparam,\n                                  LPARAM const lparam) noexcept;\n\n  // Retrieves a class instance pointer for |window|\n  static Win32Window *GetThisFromHandle(HWND const window) noexcept;\n\n  // Update the window frame's theme to match the system theme.\n  static void UpdateTheme(HWND const window);\n\n  bool quit_on_close_ = false;\n\n  // window handle for top level window.\n  HWND window_handle_ = nullptr;\n\n  // window handle for hosted content.\n  HWND child_content_ = nullptr;\n};\n\n#endif // RUNNER_WIN32_WINDOW_H_\n"
  }
]